Jak porównać dwa zestawy javascript? Próbowałem za pomocą ==
a ===
jednak zarówno fałszywie zwrotny.
a = new Set([1,2,3]);
b = new Set([1,3,2]);
a == b; //=> false
a === b; //=> false
Te dwa zbiory są równoważne, ponieważ z definicji zbiory nie mają porządku (przynajmniej nie zwykle). Przejrzałem dokumentację Set on MDN i nie znalazłem nic przydatnego. Czy ktoś wie, jak to zrobić?
javascript
set
ecmascript-6
williamcodes
źródło
źródło
===
dotyczy równości wartości, a nie równości obiektów.new Set([1,2,3]) != new Set([1,2,3])
. To sprawia, że zestaw JavaScript jest bezużyteczny dla zestawów zestawów, ponieważ nadzbiór będzie zawierał zduplikowane podzbiory. Jedynym obejściem, jakie przychodzi na myśl, jest konwersja wszystkich podzbiorów na tablice, sortowanie każdej tablicy, a następnie kodowanie każdej tablicy jako ciągu (na przykład JSON).Odpowiedzi:
Spróbuj tego:
Bardziej funkcjonalnym podejściem byłoby:
all
Funkcja działa dla wszystkich obiektów (np iterableSet
iMap
).Gdyby
Array.from
był szerzej obsługiwany, moglibyśmy zaimplementowaćall
funkcję jako:Mam nadzieję, że to pomoże.
źródło
has
naisPartOf
lubisIn
lubelem
Możesz też spróbować:
źródło
zapewnia lodash
_.isEqual()
, który dokonuje głębokich porównań. Jest to bardzo przydatne, jeśli nie chcesz pisać własnego. Od lodash 4_.isEqual()
poprawnie porównuje zestawy.źródło
Druga odpowiedź będzie działać dobrze; tutaj jest inna alternatywa.
Należy jednak pamiętać, że to jest nie robić głębokie porównania równości. Więc
zwróci wartość false. Jeśli powyższe dwa zestawy mają być uznane za równe, musimy powtórzyć oba zestawy, wykonując głębokie porównania jakości dla każdego elementu. Zastrzegamy istnienie
deepEqual
rutyny. Wtedy logika byłaby takaCo to robi: dla każdego członka s1 szukaj głęboko równego członka s2. Jeśli zostanie znaleziony, usuń go, aby nie można go było ponownie użyć. Te dwa zbiory są głęboko równe, jeśli wszystkie elementy w s1 znajdują się w s2, a s2 jest wyczerpane. Niesprawdzone.
Może się przydać: http://www.2ality.com/2015/01/es6-set-operations.html .
źródło
Żadne z tych rozwiązań nie przywraca oczekiwanej funkcjonalności do struktury danych, takiej jak zestaw zbiorów. W obecnym stanie zestaw JavaScript jest bezużyteczny do tego celu, ponieważ nadzbiór będzie zawierał zduplikowane podzbiory, które JavaScript błędnie postrzega jako odrębne. Jedynym rozwiązaniem, które przychodzi mi do głowy , jest konwersja każdego podzbioru na Array , sortowanie go, a następnie kodowanie jako String (na przykład JSON).
Rozwiązanie
Podstawowe użycie
Test ostateczny: zestaw zestawów
źródło
[...set1].sort().toString() === [...set2].sort().toString()
Powodem, dla którego twoje podejście zwraca fałsz, jest to, że porównujesz dwa różne obiekty (nawet jeśli mają tę samą zawartość), a zatem porównywanie dwóch różnych obiektów (nie odwołań, ale obiektów) zawsze zwraca błąd.
Poniższe podejście łączy dwa zestawy w jeden i po prostu głupio porównuje rozmiar. Jeśli jest taki sam, jest taki sam:
Upside : To bardzo proste i krótkie. Żadna zewnętrzna biblioteka, tylko zwykły JS
Wada : prawdopodobnie będzie to wolniejsze niż zwykłe iterowanie po wartościach i potrzebujesz więcej miejsca.
źródło
Porównanie dwóch obiektów za pomocą ==, ===
Kiedy używasz operatora
==
or===
do porównania dwóch obiektów, zawsze otrzymasz,false
chyba że te obiekty odnoszą się do tego samego obiektu . Na przykład:W przeciwnym razie == równa się false, mimo że obiekt zawiera te same wartości:
Konieczne może być rozważenie ręcznego porównania
W ECMAScript 6 możesz wcześniej przekonwertować zestawy na tablice, abyś mógł zauważyć różnicę między nimi:
UWAGA:
Array.from
to jedna ze standardowych funkcji ECMAScript 6, ale nie jest szeroko obsługiwana w nowoczesnych przeglądarkach. Sprawdź tabelę zgodności tutaj: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Browser_compatibilityźródło
b
których nie maa
?b
niea
ma członków, jest sprawdzenie, czya.size === b.size
.a.size === b.size
pierwszym miejscu zwarcie porównania poszczególnych elementów, jeśli nie jest to konieczne?has
operacje na zbiorach są zaprojektowane tak, aby były bardzo wydajne, w przeciwieństwie doindexOf
operacji na tablicach. Dlatego warto zmienić funkcję filtru nareturn !b.has(i)
. To również wyeliminowałoby potrzebę konwersjib
na tablicę.Utworzyłem szybki polyfill dla Set.prototype.isEqual ()
Github Gist - Set.prototype.isEqual
źródło
Na podstawie zaakceptowanej odpowiedzi, zakładając poparcie
Array.from
, oto jedna linijka:źródło
eqSet = (a,b) => a.size === b.size && [...a].every(b.has.bind(b))
Jeśli zbiory zawierają tylko pierwotne typy danych lub obiekty wewnątrz zbiorów mają równość odwołań, to jest prostszy sposób
const isEqualSets = (set1, set2) => (set1.size === set2.size) && (set1.size === new Set([...set1, ...set2]).size);
źródło
W testach stosuję to podejście:
źródło
a=[1,2,3]
ib=[1,2,3,4]
, zobaczysz , że są takie same. Więc myślę, że potrzebujesz dodatkowego czeku, takiego jaksetA.size === setB.size
Bardzo niewielka modyfikacja oparta na odpowiedzi @Aadit M Shah:
Jeśli ktoś inny ma problem, tak jak ja, z powodu jakiegoś dziwactwa najnowszego babel, musiał dodać tutaj wyraźny warunek.
(Również w przypadku liczby mnogiej myślę, że
are
czytanie na głos jest nieco bardziej intuicyjne 🙃)źródło
1) Sprawdź, czy rozmiary są równe. Jeśli nie, to nie są równi.
2) iteruj po każdym elemencie A i sprawdź, który istnieje w B. Jeśli jeden z nich się nie powiedzie, wróć
unequal
3) Jeśli powyższe 2 warunki nie spełnią się, oznacza to, że są równe.
2) Metoda 2
źródło
forEach
metodzie NIE spowoduje powrotu funkcji nadrzędnej.