Więcej
Usuń zduplikowane wartości z tablicy JS
Mam bardzo prostą tablicę JavaScript, która może, ale nie musi zawierać duplikatów.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
Muszę usunąć duplikaty i umieścić unikalne wartości w nowej tablicy.
Mógłbym wskazać wszystkie kody, które I've próbował, ale myślę, że to's bezużyteczne, ponieważ oni nie'działają. Akceptuję również rozwiązania jQuery.
Podobne pytanie:
1217
3
TL;DR
Używając konstruktora Set i składni spread syntax:
"Smart", ale naïve sposób
Zasadniczo iterujemy nad tablicą i dla każdego elementu sprawdzamy, czy pierwsza pozycja tego elementu w tablicy jest równa bieżącej pozycji. Oczywiście, te dwie pozycje są różne dla zduplikowanych elementów. Przy pomocy trzeciego ("ta tablica") parametru wywołania zwrotnego filtra możemy uniknąć zamknięcia zmiennej tablicowej:
Choć zwięzły, algorytm ten nie jest szczególnie wydajny dla dużych tablic (czas kwadratowy). Hashtables na ratunek
Tak to się zwykle robi. Chodzi o to, aby umieścić każdy element w tablicy hashtable, a następnie natychmiast sprawdzić jego obecność. To daje nam czas liniowy, ale ma co najmniej dwie wady:
uniq([1,"1"])
zwróci po prostu[1]
.z tego samego powodu, wszystkie obiekty będą uważane za równe:
uniq([{foo:1},{foo:2}])
zwróci tylko[{foo:1}]
. To powiedziawszy, jeśli twoje tablice zawierają tylko prymitywy i nie dbasz o typy (np. to'zawsze liczby), to rozwiązanie jest optymalne. To, co najlepsze z dwóch światówUniwersalne rozwiązanie łączy oba podejścia: używa hash lookups dla prymitywów i wyszukiwania liniowego dla obiektów.
sort | uniq
Inną opcją jest posortowanie tablicy jako pierwszej, a następnie usunięcie każdego elementu równego poprzedniemu:
Ponownie, to nie działa z obiektami (ponieważ wszystkie obiekty są równe dla
sort
). Dodatkowo, po cichu zmieniamy oryginalną tablicę jako efekt uboczny - nie jest to dobre! Jednakże, jeśli twoje dane wejściowe są już posortowane, to jest to droga do zrobienia (po prostu usuńsort
z powyższego). Unikalne przez...Czasami pożądane jest, aby zunifikować listę na podstawie innych kryteriów niż tylko równość, na przykład, aby odfiltrować obiekty, które są różne, ale mają wspólną właściwość. Można to zrobić w elegancki sposób, przekazując wywołanie zwrotne. Ten "klucz" jest stosowany do każdego elementu, a elementy z równymi "kluczami" są usuwane. Ponieważ oczekuje się, że
key
zwróci prymityw, tablica hash będzie działać dobrze tutaj:Szczególnie użytecznym
key()
jestJSON.stringify
, który usunie obiekty, które są fizycznie różne, ale "wyglądają" tak samo:Jeśli
klucz
nie jest prymitywny, trzeba uciec się do wyszukiwania liniowego:W ES6 możesz użyć
Set
:lub
Map
:które również działają z kluczami nieprymitywnymi. Pierwszy czy ostatni?
Podczas usuwania obiektów według klucza, możesz chcieć zachować pierwszy z "równych" obiektów lub ostatni. Użyj powyższego wariantu
Set
aby zachować pierwszy, orazMap
aby zachować ostatni:Biblioteki
Zarówno underscore jak i Lo-Dash dostarczają metod
uniq
. Ich algorytmy są w zasadzie podobne do pierwszego powyższego snippetu i sprowadzają się do tego:To jest quadratic, ale są tam miłe dodatkowe bajery, jak owijanie natywnego
indexOf
, możliwość uniqify przez klucz (iteratee
w ich języku), i optymalizacje dla już posortowanych tablic. Jeśli używasz jQuery i nie możesz znieść niczego bez dolara przed nim, to idzie to tak:co jest, ponownie, wariacją pierwszego snippetu. Wydajność
Wywołania funkcji są drogie w JavaScript, dlatego powyższe rozwiązania, tak zwięzłe jak są, nie są szczególnie wydajne. Aby uzyskać maksymalną wydajność, zastąp
filter
pętlą i pozbądź się innych wywołań funkcji:Ten kawałek brzydkiego kodu robi to samo, co snippet #3 powyżej, ale o rząd wielkości szybciej (od 2017 roku jest'tylko dwa razy szybszy - ludzie z JS core robią świetną robotę!)
ES6
ES6 dostarcza obiekt Set, który znacznie ułatwia sprawę:
lub
Zauważ, że w przeciwieństwie do pythona, zestawy ES6 są iterowane w kolejności wstawiania, więc ten kod zachowuje kolejność oryginalnej tablicy. Jednakże, jeśli potrzebujesz tablicy z unikalnymi elementami, dlaczego nie użyć zestawów od samego początku? Generatory
Na tej samej zasadzie można zbudować "leniwą", opartą na generatorach wersję
uniq
:Szybkie i brudne użycie jQuery:
Vanilla JS: Usuń duplikaty używając obiektu jak zbioru.
Zawsze możesz spróbować umieścić go w obiekcie, a następnie iterować po jego kluczach:
Vanilla JS: Usuń duplikaty poprzez śledzenie już widzianych wartości (order-safe).
Lub, dla wersji bezpiecznej dla porządku, użyj obiektu do przechowywania wszystkich wcześniej widzianych wartości i sprawdź wartości z nim przed dodaniem do tablicy.
ECMAScript 6: Użyj nowej struktury danych Set (order-safe).
ECMAScript 6 dodaje nową strukturę danych
Set
, która pozwala na przechowywanie wartości dowolnego typu. StrukturaSet.values
zwraca elementy w kolejności wstawiania.Przykładowe użycie: