Mam dwa takie zestawy wyników:
// Result 1
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
{ value: "4", display: "Ryan" }
]
// Result 2
[
{ value: "0", display: "Jamsheer" },
{ value: "1", display: "Muhammed" },
{ value: "2", display: "Ravi" },
{ value: "3", display: "Ajmal" },
]
Ostateczny wynik, jakiego potrzebuję, to różnica między tymi tablicami - ostateczny wynik powinien wyglądać następująco:
[{ value: "4", display: "Ryan" }]
Czy można zrobić coś takiego w JavaScript?
javascript
arrays
object
BKM
źródło
źródło
Odpowiedzi:
Używając tylko natywnego JS, zadziała coś takiego:
źródło
return a.value ===...
w twojej odpowiedzi? (Nawiasem mówiąc, fajne rozwiązanie, +1) Oprócz używaniaArray.prototype.some()
, nie mogę znaleźć bardziej wydajnego / krótszego sposobu na zrobienie tego.true
lubfalse
wartość). W tym przypadku, jeśli oddzielimy pojęcie testowania równości od reszty kodu, wymagając od użytkownika przejścia sprawdzenia równości jako funkcji, możemy prosty algorytm ogólny.Możesz użyć
Array.prototype.filter()
w połączeniu zArray.prototype.some()
.Oto przykład (zakładając, że twoje tablice są przechowywane w zmiennych
result1
iresult2
):źródło
Dla tych, którzy lubią jednowierszowe rozwiązania w ES6, coś takiego:
źródło
Przyjmuję nieco bardziej ogólne podejście, chociaż pomysły są podobne do podejść @Cerbrus i @Kasper Moerch . Tworzę funkcję, która przyjmuje predykat, aby określić, czy dwa obiekty są równe (tutaj ignorujemy tę
$$hashKey
właściwość, ale może to być cokolwiek) i zwracam funkcję, która oblicza symetryczną różnicę dwóch list na podstawie tego predykatu:Ma jedną niewielką przewagę nad podejściem Cerebrusa (podobnie jak podejście Kaspera Moercha), ponieważ ucieka wcześnie; jeśli znajdzie dopasowanie, nie przejmuje się sprawdzaniem reszty listy. Gdybym miał pod
curry
ręką funkcję, zrobiłbym to trochę inaczej, ale to działa dobrze.Wyjaśnienie
W komentarzu prosiliśmy o bardziej szczegółowe wyjaśnienie dla początkujących. Oto próba.
Przekazujemy następującą funkcję do
makeSymmDiffFunc
:Ta funkcja pozwala stwierdzić, że dwa obiekty są równe. Podobnie jak wszystkie funkcje, które zwracają wartość
true
lubfalse
, można ją nazwać „funkcją predykatu”, ale to tylko terminologia. Najważniejsze jest to, żemakeSymmDiffFunc
jest skonfigurowana z funkcją, która przyjmuje dwa obiekty i zwraca,true
jeśli uznamy je za równe,false
jeśli nie.Używając tego,
makeSymmDiffFunc
(czytaj "funkcja tworzenia symetrycznej różnicy") zwraca nam nową funkcję:To jest funkcja, której będziemy faktycznie używać. Przekazujemy mu dwie listy i znajduje elementy w pierwszej, a nie w drugiej, a następnie elementy w drugiej nie na pierwszej i łączy te dwie listy.
Jednak patrząc jeszcze raz, zdecydowanie mogłem wziąć wskazówkę z twojego kodu i całkiem uprościć główną funkcję, używając
some
:complement
używa predykatu i zwraca elementy swojej pierwszej listy, a nie drugiej. To jest prostsze niż mój pierwszy przebieg z oddzielnącontains
funkcją.Wreszcie funkcja główna jest opakowana w natychmiast wywołane wyrażenie funkcyjne ( IIFE ), aby utrzymać funkcję wewnętrzną
complement
poza zasięgiem globalnym.Aktualizacja, kilka lat później
Teraz, gdy ES2015 stał się całkiem nieźle wszechobecny, sugerowałbym tę samą technikę, z dużo mniejszą liczbą schematów:
źródło
To zwróci różnicę między dwiema tablicami obiektów, używając klucza
value
do ich porównania. Zauważ, że dwie rzeczy o tej samej wartości nie zostaną zwrócone, ponieważ inne klucze są ignorowane.To jest część lodash .
źródło
Możesz utworzyć obiekt z kluczami jako unikatową wartością odpowiadającą każdemu obiektowi w tablicy, a następnie filtrować każdą tablicę na podstawie istnienia klucza w obiekcie innej osoby. Zmniejsza złożoność operacji.
ES6
ES5
źródło
Myślę, że rozwiązanie @Cerbrus jest na miejscu. Zaimplementowałem to samo rozwiązanie, ale wyodrębniłem powtórzony kod do własnej funkcji (DRY).
źródło
Znalazłem to rozwiązanie za pomocą filtra i niektórych.
źródło
Większość odpowiedzi tutaj jest dość złożona, ale czy logika nie stoi za tym całkiem prosta?
O (n ^ 2) złożoność.
źródło
możesz zrobić diff a na b i diff b na a, a następnie połączyć oba wyniki
źródło
Zrobiłem uogólniony diff, który porównuje 2 obiekty dowolnego rodzaju i może uruchomić program obsługi modyfikacji gist.github.com/bortunac "diff.js" , przykład użycia:
więc właściwość a jest modyfikowana, b jest usuwana, c modyfikowana, d jest dodawane
}
teraz użyj like
konsola pokaże
źródło
Najbardziej ogólny i prosty sposób:
źródło
Preferuję obiekt mapy, jeśli chodzi o duże tablice.
źródło
JavaScript ma mapy, które zapewniają O (1) czas wstawiania i wyszukiwania. Dlatego można to rozwiązać w O (n) (a nie w O (n²), jak wszystkie inne odpowiedzi). W tym celu konieczne jest wygenerowanie unikalnego klucza pierwotnego (ciąg / numer) dla każdego obiektu. Można
JSON.stringify
, ale jest to dość podatne na błędy, ponieważ kolejność elementów może wpływać na równość:Dlatego wziąłbym separator, który nie pojawia się w żadnej z wartości i ręcznie skomponowałbym ciąg:
Następnie tworzona jest mapa. Gdy element już istnieje na mapie, zostaje usunięty, w przeciwnym razie zostaje dodany. Dlatego pozostają tylko te elementy, które zawierają nieparzyste czasy (czyli tylko raz). To zadziała tylko wtedy, gdy elementy są unikalne w każdej tablicy:
Pokaż fragment kodu
źródło
Natknąłem się na to pytanie, szukając sposobu na wybranie pierwszego elementu w jednej tablicy, który nie pasuje do żadnej z wartości w innej tablicy, i ostatecznie udało mi się go uporządkować za pomocą array.find () i array.filter (), jak to
jeśli chcesz nadal pobierać zaktualizowaną listę przed sprawdzeniem następnej najlepszej opcji, powinno to działać wystarczająco dobrze :)
źródło
Jeśli chcesz korzystać z bibliotek zewnętrznych, możesz użyć _.difference w pliku underscore.js, aby to osiągnąć. _.difference zwraca wartości z tablicy, których nie ma w innych tablicach.
źródło