Mam szereg liczb, które muszę upewnić się, że są unikalne. Fragment kodu znalazłem poniżej w Internecie i działa świetnie, dopóki tablica nie będzie miała zera. Znalazłem ten inny skrypt tutaj na przepełnieniu stosu, który wygląda prawie dokładnie tak, ale nie zawodzi.
Czy więc, aby pomóc mi w nauce, ktoś może mi pomóc ustalić, gdzie źle działa prototypowy skrypt?
Array.prototype.getUnique = function() {
var o = {}, a = [], i, e;
for (i = 0; e = this[i]; i++) {o[e] = 1};
for (e in o) {a.push (e)};
return a;
}
Więcej odpowiedzi z duplikatu pytania:
Podobne pytanie:
javascript
arrays
unique
Mottie
źródło
źródło
o
=object
,a
=array
,i
=index
ie
= umm, coś: POdpowiedzi:
W JavaScript 1.6 / ECMAScript 5 możesz użyć natywnej
filter
metody Array w następujący sposób, aby uzyskać tablicę o unikalnych wartościach:Metoda natywna
filter
będzie pętla w tablicy i pozostawi tylko te wpisy, które przejdą daną funkcję wywołania zwrotnegoonlyUnique
.onlyUnique
sprawdza, czy podana wartość występuje po raz pierwszy. Jeśli nie, musi być duplikatem i nie zostanie skopiowany.To rozwiązanie działa bez dodatkowej biblioteki, takiej jak jQuery lub prototype.js.
Działa również w przypadku tablic o mieszanych typach wartości.
Dla starych przeglądarek (<IE9), które nie obsługują metod natywnych
filter
iindexOf
można znaleźć arounds praca w dokumentacji MDN na filtrze i indexOf .Jeśli chcesz zachować ostatnie wystąpienie wartości, po prostu zamień
indexOf
nalastIndexOf
.Z ES6 można to skrócić do tego:
Podziękowania dla Camilo Martina za podpowiedź w komentarzu.
ES6 ma obiekt macierzysty
Set
do przechowywania unikalnych wartości. Aby uzyskać tablicę z unikalnymi wartościami, możesz teraz zrobić to:Konstruktor
Set
pobiera iterowalny obiekt, taki jak Array, a operator rozkładania...
przekształca zestaw z powrotem w Array. Podziękowania dla Lukasa Liese za podpowiedź w komentarzu.źródło
['a', 1, 'a', 2, '1']
dostaniesz['a', 1, 2]
. Ale nie tego się spodziewałem. BTW, znacznie wolniejszy jest bardzo względny..filter((v,i,a)=>a.indexOf(v)==i)
(zapis grubej strzały).let unique_values = [...new Set(random_array)];
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Zaktualizowana odpowiedź dla ES6 / ES2015 : Przy użyciu zestawu rozwiązanie jednoliniowe to:
Który zwraca
Jak sugeruje le_m , można to również skrócić za pomocą operatora spread , np
źródło
Array.from(new Set([[1,2],[1,2],[1,2,3]]))
myArray.filter((v, i, a) => a.indexOf(v) === i);
?Set
i dodasz obiekty zamiast pierwotnych wartości, będą one zawierały unikalne odniesienia do obiektów. Zatem zestaws
wlet s = new Set([{Foo:"Bar"}, {Foo:"Bar"}]);
zwróci to:Set { { Foo: 'Bar' }, { Foo: 'Bar' } }
co jestSet
unikalnym odwołaniem do obiektu, który zawiera te same wartości. Jeśli napiszesz,let o = {Foo:"Bar"};
a następnie utworzysz zestaw z dwoma odnośnikami : taklet s2 = new Set([o,o]);
, wtedy s2 będzieSet { { Foo: 'Bar' } }
new Set
trofeumZdaję sobie sprawę, że to pytanie ma już ponad 30 odpowiedzi. Ale najpierw przeczytałem wszystkie istniejące odpowiedzi i przeprowadziłem własne badania.
Podzielę wszystkie odpowiedzi na 4 możliwe rozwiązania:
[...new Set( [1, 1, 2] )];
{ }
aby zapobiec duplikatom[ ]
filter + indexOf
Oto przykładowe kody znalezione w odpowiedziach:
Użyj nowej funkcji ES6:
[...new Set( [1, 1, 2] )];
Użyj obiektu,
{ }
aby zapobiec duplikatomUżyj tablicy pomocniczej
[ ]
Posługiwać się
filter + indexOf
I zastanawiałem się, który z nich jest szybszy. Zrobiłem przykładowy Arkusz Google do testowania funkcji. Uwaga: ECMA 6 nie jest dostępny w Arkuszach Google, więc nie mogę go przetestować.
Oto wynik testów:
Spodziewałem się, że kod wykorzystujący obiekt
{ }
wygra, ponieważ używa skrótu. Cieszę się więc, że testy wykazały najlepsze wyniki dla tego algorytmu w Chrome i IE. Dzięki @rab za kod .źródło
Możesz także użyć underscore.js .
który zwróci:
źródło
array = [...new Set(array)]
One Liner, czysty JavaScript
Ze składnią ES6
list = list.filter((x, i, a) => a.indexOf(x) == i)
Ze składnią ES5
Kompatybilność przeglądarki : IE9 +
źródło
Od tego czasu znalazłem fajną metodę, która używa jQuery
Uwaga: ten kod został pobrany z kaczy Paula Irlandczyka - zapomniałem podać kredyt: P
źródło
Najkrótsze rozwiązanie z ES6:
[...new Set( [1, 1, 2] )];
Lub jeśli chcesz zmodyfikować prototyp Array (jak w pierwotnym pytaniu):
EcmaScript 6 jest obecnie tylko częściowo zaimplementowany w nowoczesnych przeglądarkach (sierpień 2015), ale Babel stał się bardzo popularny przy transpilowaniu ES6 (a nawet ES7) z powrotem do ES5. W ten sposób możesz napisać kod ES6 już dziś!
Jeśli zastanawiasz się, co to
...
znaczy, nazywa się to operatorem rozprzestrzeniania . Z MDN : «Operator rozkładania pozwala na rozwinięcie wyrażenia w miejscach, w których oczekuje się wielu argumentów (dla wywołań funkcji) lub wielu elementów (dla literałów tablicowych)». Ponieważ zestaw jest iterowalny (i może mieć tylko unikalne wartości), operator rozkładania rozszerzy zestaw, aby wypełnić tablicę.Materiały do nauki ES6:
źródło
a = [...Set(a)]
ale na razie jest to tylko Firefox.require ( "core-js/fn/array/from" );
[...Set(['a', 1, 'a', 2, '1'])]
zgłosi błąd typu TypeError, więc nadal mądrze jest zachowaćnew
:[...new Set(['a', 1, 'a', 2, '1'])]
Najprostsze rozwiązanie:
Lub:
źródło
Najprostszy i najszybszy (w Chrome) sposób:
Po prostu przechodzi przez każdy element w tablicy, sprawdza, czy ten element jest już na liście, a jeśli nie, przesuń do tablicy, która zostanie zwrócona.
Według jsPerf ta funkcja jest najszybsza z tych, jakie mogłem znaleźć wszędzie - możesz jednak dodać własną.
Nieprototypowa wersja:
Sortowanie
Gdy trzeba również posortować tablicę, najszybsze są następujące czynności:
lub nieprototypowy:
Jest to również szybsze niż powyższa metoda w większości przeglądarek innych niż Chrome.
źródło
unique
funkcji ma złożoność O (n ^ 2), podczas gdy ten wgetUnique
to O (n). Pierwszy może być szybszy na małych zestawach danych, ale jak możesz się kłócić z matematyką :) Możesz upewnić się, że ten drugi jest szybszy, jeśli uruchomisz go na szeregu, powiedzmy, 1e5 unikalnych przedmiotówTYLKO WYDAJNOŚĆ! ten kod jest prawdopodobnie 10 razy szybszy niż wszystkie kody tutaj * działa na wszystkich przeglądarkach, a także ma najmniejszy wpływ na pamięć .... i więcej
jeśli nie musisz ponownie używać starej tablicy; btw wykonaj niezbędne operacje, zanim skonwertujesz ją na unikalną, jest to prawdopodobnie najszybszy sposób na zrobienie tego, również bardzo krótki.
to możesz spróbować
Wymyśliłem tę funkcję, czytając ten artykuł ...
http://www.shamasis.net/2009/09/fast-alameterm-to-find-unique-items-in-javascript-array/
Nie lubię pętli for. ma wiele parametrów. lubię pętlę while--. podczas gdy jest najszybszą pętlą we wszystkich przeglądarkach oprócz tej, którą wszyscy bardzo lubimy ... chrome.
w każdym razie napisałem pierwszą funkcję, która używa while. Tak, jest to trochę szybsze niż funkcja znaleziona w artykule. ale za mało.
unique2()
w następnym kroku użyj nowoczesnego js.
Object.keys
drugą pętlę for zastąpiłem Object.keys js1.7 ... trochę szybciej i krócej (w chrome 2x szybciej);). Niewystarczająco!.unique3()
.w tym momencie myślałem o tym, czego naprawdę potrzebuję w MOJEJ unikalnej funkcji. nie potrzebuję starej tablicy, chcę szybkiej funkcji. więc użyłem 2 pętli while + splot.
unique4()
Nie trzeba dodawać, że byłem pod wrażeniem.
chrome: zwykłe 150 000 operacji na sekundę skoczyło do 1 800 000 operacji na sekundę.
tj. 80 000 operacji na sekundę w porównaniu do 35 000 000 operacji na sekundę
ios: 18 000 operacji na sekundę vs 170 000 operacji na sekundę
safari: 80 000 operacji na sekundę vs 6 000 000 operacji na sekundę
Dowód http://jsperf.com/wgu lub lepiej użyj console.time ... microtime ... cokolwiek
unique5()
jest po prostu pokazanie, co się stanie, jeśli chcesz zachować starą tablicę.Nie używaj,
Array.prototype
jeśli nie wiesz, co robisz. właśnie zrobiłem dużo kopii i przeszłości. Użyj,Object.defineProperty(Array.prototype,...,writable:false,enumerable:false})
jeśli chcesz utworzyć natywny prototyp. Przykład : https://stackoverflow.com/a/20463021/2450730Demo http://jsfiddle.net/46S7g/
UWAGA: twoja stara tablica jest niszczona / staje się unikalna po tej operacji.
jeśli nie możesz odczytać powyższego kodu, zapytaj, przeczytaj książkę javascript lub oto wyjaśnienia dotyczące krótszego kodu. https://stackoverflow.com/a/21353032/2450730
niektórzy używają
indexOf
... nie ... http://jsperf.com/dgfgghfghfghghgfhgfhfghfhgfhdla pustych tablic
źródło
Wiele odpowiedzi tutaj może nie być przydatnych dla początkujących. Jeśli odkodowanie tablicy jest trudne, czy naprawdę będą wiedzieć o łańcuchu prototypów, a nawet o jQuery?
W nowoczesnych przeglądarkach czystym i prostym rozwiązaniem jest przechowywanie danych w zestawie , który ma być listą unikalnych wartości.
Array.from
Jest przydatna do konwersji cofnięty do tablicy tak, że masz łatwy dostęp do wszystkich wspaniałych metod (cechy), które mają tablice. Istnieją również inne sposoby robienia tego samego. Ale może nie być wcale potrzebnyArray.from
, ponieważ zestawy mają wiele przydatnych funkcji, takich jak forEach .Jeśli potrzebujesz obsługi starego programu Internet Explorer, a zatem nie możesz użyć zestawu, prostą techniką jest skopiowanie elementów do nowej tablicy, uprzednio sprawdzając, czy są już w nowej tablicy.
Aby umożliwić natychmiastowe ponowne użycie, włączmy funkcję.
Aby pozbyć się duplikatów, zrobilibyśmy to teraz.
deduplicate(cars)
Część staje się rzeczą nazwaliśmy wynik gdy finalizuje funkcyjnych.Po prostu podaj nazwę dowolnej tablicy, którą lubisz.
źródło
źródło
push
elementu na tablicy zamiast go używaćconcat
? Próbowałem użyć wypychania i nie udało się. Szukam wyjaśnienia.[0,1,2,0,3,2,1,5].reduce((prev, cur) => ~prev.indexOf(cur) ? prev : prev.concat([cur]), []);
NaN
przyjaznaMożemy to zrobić za pomocą zestawów ES6:
// Wyjście będzie
źródło
Ten prototyp
getUnique
nie jest całkowicie poprawny, ponieważ jeśli mam tablicę typu:["1",1,2,3,4,1,"foo"]
zwróci["1","2","3","4"]
i"1"
jest ciągiem i1
jest liczbą całkowitą; oni są różni.Oto prawidłowe rozwiązanie:
za pomocą:
Powyższe spowoduje
["1",2,3,4,1,"foo"]
.źródło
$foo = 'bar'
jest to sposób deklarowania zmiennych w PHP. Będzie działał w javascript, ale stworzy domyślną globalną i na ogół nie powinno się tego robić.$foo
jest to sposób deklarowania zmiennych w javascript, podczas gdy tak naprawdęvar foo
jest.Bez rozszerzenia Array.prototype (mówi się, że jest to zła praktyka) lub użycia jquery / podkreślenia, możesz po prostu
filter
tablicę.Zachowując ostatnie wystąpienie:
lub pierwsze wystąpienie:
Cóż, to tylko javascript ECMAScript 5+, co oznacza tylko IE9 +, ale jest przyjemny dla rozwoju w natywnym HTML / JS (aplikacja Windows Store, Firefox OS, Sencha, Phonegap, Titanium, ...).
źródło
filter
. Na stronie MDN mają implementację dla Internet Explorera, to znaczy starszych przeglądarek. Ponadto: JS 1.6 odnosi się tylko do silnika js Firefoksa, ale należy powiedzieć, że jest to ECMAScript 5.magia
O (n) wydajność ; zakładamy, że twoja tablica jest w
a
it={}
. Objaśnienie tutaj (+ Jeppe impr.)Pokaż fragment kodu
źródło
in
operatora poza konstrukcją inną niżfor
pętla: P) - Dziękuję - doceniam to i dam +2 do twoich innych dobrych odpowiedzi .t
która utrzymuje się przy życiu po filtrowaniu… ??źródło
Jeśli używasz Prototype Framework, nie musisz wykonywać pętli „for”, możesz użyć http://www.prototypejs.org/api/array/uniq w następujący sposób:
Który wytworzy duplikat tablicy bez duplikatów. Natknąłem się na twoje pytanie, szukając metody zliczania różnych rekordów tablic, więc potem
użyłem
i był mój prosty wynik. ps Przepraszam, jeśli coś źle wpisałem
edycja: jeśli chcesz uciec niezdefiniowanym rekordom, możesz je dodać
wcześniej, tak:
źródło
Teraz za pomocą zestawów możesz usunąć duplikaty i przekonwertować je z powrotem do tablicy.
Innym rozwiązaniem jest użycie sortowania i filtrowania
źródło
To dlatego, że
0
jest to wartość fałsz w JavaScript.this[i]
będzie fałszem, jeśli wartość tablicy wynosi 0 lub dowolna inna wartość fałszowania.źródło
źródło
o
zamiast po prostu1
, chociaż porównanie równości nadal byłoby rygorystyczne (chociaż ze wszystkich możliwych równości Javascript nie wydaje się to zbyt nierozsądne).Miałem nieco inny problem, w którym musiałem usunąć obiekty z duplikatami właściwości id z tablicy. to zadziałało.
źródło
Najprostsza odpowiedź to:
źródło
Nie jestem pewien, dlaczego Gabriel Silveira napisał tę funkcję w ten sposób, ale prostsza forma, która działa dla mnie równie dobrze i bez minimalizacji, to:
lub w CoffeeScript:
źródło
Jeśli nie masz nic przeciwko dodatkowym zależnościom lub masz już jedną z bibliotek w bazie kodu, możesz usunąć duplikaty z tablicy za pomocą LoDash (lub Underscore).
Stosowanie
Jeśli nie masz go jeszcze w swojej bazie kodu, zainstaluj go za pomocą npm:
Następnie użyj go w następujący sposób:
Na zewnątrz:
źródło
Odpowiedzi udzielono na wiele, ale nie zaspokoiło to mojej szczególnej potrzeby.
Wiele odpowiedzi jest takich:
Ale to nie działa w przypadku tablic złożonych obiektów.
Powiedzmy, że mamy taką tablicę:
Jeśli chcemy obiektów o unikalnych nazwach, powinniśmy użyć
array.prototype.findIndex
zamiastarray.prototype.indexOf
:źródło
Od Shamasis Bhattacharya „s blog (O (2n) czasu złożoności):
Z bloga Paula Irisha : poprawa JQuery
.unique()
:źródło
Znajdowanie unikalnych wartości tablic w prosty sposób
źródło
Wygląda na to, że utraciliśmy odpowiedź Rafaela , która przez kilka lat stała się odpowiedzią przyjętą. Było to (przynajmniej w 2017 r.) Najskuteczniejsze rozwiązanie, jeśli nie masz tablicy typu mieszanego :
Jeśli zrobić posiada tablicę mieszany typu można szeregować klawisz skrótu:
źródło
Aby rozwiązać ten problem na odwrót, przydatne może być brak duplikatu podczas ładowania tablicy, tak jak zrobiłby to obiekt Set , ale nie jest jeszcze dostępny we wszystkich przeglądarkach. Oszczędza pamięć i jest bardziej wydajna, jeśli trzeba wielokrotnie przeglądać jej zawartość.
Próba:
Daje Ci
set = [1,3,4,2]
źródło