Laczenie 2 obiektow po kluczu

0

mam problem poniewaz mam taka tablice

[
{
category: "cat-2",
time: [2,3,4,5]
},
{
category: "cat-3",
time: [2,3,4]
},
{
category: "cat-2",
time: [1, 2,3,4]
},
{
category: "cat-4",
time: [2,3,4]
}
]

I chce stworzyc taka saa tablice ale zlaczyc je po powtarzalnej kategori bo nie zawsze bedzie powtorzona cat-2 a tablica aby byla zlaczona unikalnie czyli nie powtarzaly sie te elementy.

0

Tzn. jaki ma być efekt końcowy?

0
LukeJL napisał(a):

Tzn. jaki ma być efekt końcowy?

W skrocie mamy taka tablice

[
{
category: "cat-2",
time: [2,3,4,5]
},
{
category: "cat-3",
time: [2,3,4]
},
{
category: "cat-2",
time: [1, 2,3,4]
},
{
category: "cat-4",
time: [2,3,4]
}
]


a z niej chce otrzymac taka


[
{
category: "cat-2",
time: [1,2,3,4,5]
},
{
category: "cat-3",
time: [2,3,4]
},
{
category: "cat-4",
time: [2,3,4]
}
]

Czyli nie powtarzamy cat-2 ale sumujemy tablice w time bez powtorzen

1

Jak już zidentyfikujesz, że dane elementy są takie same i zdecydujesz się połączyć ich tablicę to musisz wykonać na nich następującą operację, żeby powstała jedna wspólna z unikatowymi wartościami

Array.from(new Set([...tablica1, ...tablica2]));
0

No wlasnie o to wszystko chodzi jak zidentyfikowac ze sa takie same i jak polaczyc to

0
function arrayUnique(a) {
  for (var i = 0; i < a.length; ++i) {
    for (var j = i+1 ; j < a.length; ++j) {
      if (a[i].category === a[j].category){
                     a[i].time = Array.from(new Set([...a[i].time, ...a[j].time]));
        a.splice(j--, 1);
        }
   
    }
  }

  return a;
};

console.log(arrayUnique([
{
category: "cat-2",
time: [2,3,4,5,8]
},
{
category: "cat-3",
time: [2,3,4]
},
{
category: "cat-2",
time: [1, 2,3,4,9]
},
{
category: "cat-4",
time: [2,3,4]
}
]));

Tylko to rozwiązanie na pewno do najszybszych nie należy mając to musisz jeszcze popracować nad algorytmem.

0

możesz zrobić sobie "słownik" (czyli w JS obiekt Map ew. normalny obiekt, które też można używać jako słowniki, o ile ma się świadomość pewnych pułapek i ograniczeń), który będzie indeksowany po danej kategorii.

a potem przeiterować tablicę i zobaczyć, czy obiekt o danym kluczu jest w słowniku, czy go nie ma. Jeśli nie ma, to wrzucasz do słownika, jeśli jest, to bierzesz istniejący i dodajesz do niego dane.
Coś jak to:


const map = new Map();

arr1.forEach(item => {
    let cached = map.get(item.category) || item;
     // sztuczka z new Set do likwidacji duplikatów z tablicy
    cached.time = Array.from(new Set(cached.time.concat(item.time))).sort();
    map.set(item.category, cached);
});

const arr2 = Array.from(map.values());

0

Widzę już ktoś odpowiedział, ale ja też na szybko coś wysmażyłem, więc szkoda nie zamieścić :). Za bardzo nie testowane i pewnie można to zrobić wydajniej:

function merge(...arrays) {
    const tempArr = [];
    arrays.forEach((arr) => {
        arr.forEach((el) => {
            let index = tempArr.findIndex(item => el.category === item.category);
            if (index !== -1) {
                tempArr[index].time = [...new Set(tempArr[index].time.concat(el.time))];
            } else {
                tempArr.push(el);
            }
        })
    })
    return tempArr;
}


merge(arr1, arr2);
0

dziekuje dzia\la :)

0

W sumie można jeszcze inaczej i trochę krócej ;)

arr.reduce((result, { category, time }) => {
  result[category] = {
    category,
    time: [
      ...new Set([
        ...((result[category] && result[category].time) || []),
        ...time,
      ]),
    ],
  };

  return result;
}, {});
1

Słyszeliście kiedyś o złożoności obliczeniowej?

Dżawaskrypciarze. :D

0

No mój przykład zakłada konwersję do mapy, właśnie żeby (przynajmniej teoretycznie) tę złożoność obniżyć i nie wyszukiwać w całej tablicy co chwila, tylko się odwołać do mapy.

(pytanie tylko jaką rzeczywistą złożoność ma obiekt Map w JS. No i pytanie o rzeczywistą implementację Map w silniku JSa. Kiedyś robiłem sobie benchmarki i wyszło mi, że obiekt Map jest dość wolny w porównaniu do zwykłych obiektów używanych jako słownik. No ale w sumie to kwestia bardziej optymalizacji silników JS).

Druga kwestia, że w moim kodzie jest pewna dodatkowa nieefektywność:

    let cached = map.get(item.category) || item;
     // sztuczka z new Set do likwidacji duplikatów z tablicy
    cached.time = Array.from(new Set(cached.time.concat(item.time))).sort();

jeśli nie ma czegoś w mapie, to przypisujemy referencję do item do zmiennej cached.
Czyli w rezultacie będzie on (w tym przypadku) robił w kolejnej linijce item.time.concat(item.time), co nie ma wielkiego sensu (dodawanie takiej samej tablicy do siebie), a może spowodować jakiś tam spadek wydajności.

No i to sortowanie w każdej iteracji, też nie wiem, czy to dobry pomysł. Nie mówiać juz o tworzeniu obiektu Set co chwila, i nowej tablicy.

Z drugiej strony to tylko przykład na forum. Jeśli bym to bardziej zoptymalizował, to mogłoby być mniej czytelne. A poza tym "premature optimization..." i tak dalej ;) Nie zawsze jest potrzebny super wydajny kod. Bo ten wydajny wyglądałby trochę jak assembler.

0

sortowanie w każdej iteracji, też nie wiem, czy to dobry pomysł.

:D

premature optimization

Poprawienie złożoności algorytmu jest według Ciebie premature optimization. Świetnie. Gdybym Cię poprosił o napisanie funkcji sortującej zaklepałbyś bogosort, zadowolony z siebie argumentując, że implementacja jest krótka i zrozumiała nawet dla debila. :D

while (!sorted(xs)) {
    shuffle(xs)
}

Przedwczesna optymalizacja w cytowanej przez Ciebie publikacji (której oczywiście nie przeczytałeś) nie odnosi się do złożoności. Zresztą, w tym samym papierku paragraf wcześniej: In established engineering disciplines a 12% improvement, easily obtained, is never considered marginal; and I believe the same viewpoint should prevail in software engineering.

0

Poprawienie złożoności algorytmu jest według Ciebie premature optimization.

Zależy jaki jest use case.

Jeśli odpalamy coś raz albo co jakiś czas, to naprawdę może to być niewydajne a i tak użytkownik nie zobaczy.

Co innego funkcja, która odpala się 60 razy na sekundę.

Jak odpalamy coś dla małego zbioru danych, to też możemy zrobić coś niewydajne, a też będzie rybka.

Co innego jak mamy tych danych więcej,

Jednak dzisiaj często ważniejszy jest czas programisty niż czas wykonywania skryptu. Takie czasy.

Pogrubiłem "często", bo niestety nie zawsze i traktowanie sprawy "olejmy wydajność całkowicie" skutkuje tym, że teraz byle stronki internetowe zamulają strasznie, bo już nikt niczego nie optymalizuje. Kiedyś się szlifowało każdą linijkę i usuwało każdą niepotrzebną rzecz z kodu - teraz hulaj dusza, liczy się tylko "time to market", jak szybko dany ficzer wejdzie na produkcję). No ale przesada w drugą stronę "wydajność ponad wszystko" też moim zdaniem nie jest dobra. A przynajmniej nie do każdego rodzaju aplikacji (przy robieniu silnika gier to pewnie takie podejście skupione w 100% na wydajności byłoby super, przy robieniu apki biznesowej pewnie niekoniecznie, bo bardziej by się liczył czas programisty spędzony na implementowaniu ficzera niż to, czy się uruchomi całość w 0.01 sekundy czy w 0.05 sekundy).

No ale nawet w apkach biznesowych są miejsca, gdzie jednak potrzeba tej wydajności, więc do pewnego stopnia mogę ci przyznać rację.

1 użytkowników online, w tym zalogowanych: 0, gości: 1