Usuń zduplikowane wartości z tablicy js [duplicate]
To pytanie ma już odpowiedź tutaj:
Mam bardzo prostą tablicę JavaScript, która może lub nie musi zawierać duplikaty.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
Muszę usunąć duplikaty i umieścić unikalne wartości w nowej tablicy.
Mogę wskazać wszystkie kody, które Próbowałem, ale myślę, że to bezużyteczne, ponieważ nie działają. Akceptuję również rozwiązania jQuery.
Podobne pytanie:
30 answers
Szybkie i brudne korzystanie z jQuery:
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniqueNames = [];
$.each(names, function(i, el){
if($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-26 10:53:59
"mądry", ale naiwny sposób
uniqueArray = a.filter(function(item, pos) {
return a.indexOf(item) == pos;
})
W zasadzie iterujemy 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 duplikatów elementów.
Używając parametru 3rd ("this array") wywołania zwrotnego filtra możemy uniknąć zamknięcia zmiennej array:
uniqueArray = a.filter(function(item, pos, self) {
return self.indexOf(item) == pos;
})
Chociaż zwięzły, algorytm ten nie jest szczególnie wydajny dla dużych tablic (czas kwadratowy).
Hashtables to the rescue
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
Tak to się zwykle robi. Chodzi o to, aby umieścić każdy element w hashtable, a następnie natychmiast sprawdzić jego obecność. Daje nam to czas liniowy, ale ma co najmniej dwie wady:]}
- ponieważ klucze hash mogą być tylko łańcuchami w Javascript, ten kod nie rozróżnia liczb i "łańcuchów liczbowych". Oznacza to, że
uniq([1,"1"])
powróci tylko[1]
- Z tego samego powodu, wszystkie obiekty będą rozpatrywane equal:
uniq([{foo:1},{foo:2}])
zwróci tylko[{foo:1}]
.
To powiedziawszy, jeśli Twoje tablice zawierają tylko pierwiastki i nie dbasz o typy (np. zawsze są to liczby), To rozwiązanie jest optymalne.
The best from two worlds
Uniwersalne rozwiązanie łączy oba podejścia: używa wyszukiwań hashowych dla prymitywów i liniowego wyszukiwania obiektów.
function uniq(a) {
var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];
return a.filter(function(item) {
var type = typeof item;
if(type in prims)
return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
else
return objs.indexOf(item) >= 0 ? false : objs.push(item);
});
}
Sort / uniq
Inną opcją jest najpierw posortowanie tablicy, a następnie usunięcie każdego elementu równego poprzedzającemu jeden:
function uniq(a) {
return a.sort().filter(function(item, pos, ary) {
return !pos || item != ary[pos - 1];
})
}
Ponownie, to nie działa z obiektami (ponieważ wszystkie obiekty są równe dla sort
). Dodatkowo po cichu zmieniamy oryginalną tablicę jako efekt uboczny-niedobrze! Jeśli jednak Dane wejściowe są już posortowane, jest to droga do zrobienia (po prostu usuń sort
z powyższego).
Unique by...
Czasami pożądane jest uniknięcie listy w oparciu o kryteria inne 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ć elegancko, przechodząc oddzwanianie. To wywołanie zwrotne "klucz" jest stosowane do każdego elementu, a elementy z równymi "kluczami" są usuwane. Ponieważ oczekuje się, że key
zwróci prymitywny, tabela hash będzie działać dobrze tutaj:
function uniqBy(a, key) {
var seen = {};
return a.filter(function(item) {
var k = key(item);
return seen.hasOwnProperty(k) ? false : (seen[k] = true);
})
}
Szczególnie przydatnym key()
jest JSON.stringify
, który usuwa obiekty, które są fizycznie różne, ale "wyglądają" tak samo:
a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]
Jeśli key
nie jest prymitywne, musisz uciekać się do wyszukiwania liniowego:
function uniqBy(a, key) {
var index = [];
return a.filter(function (item) {
var k = key(item);
return index.indexOf(k) >= 0 ? false : index.push(k);
});
}
Lub użyj obiektu Set
w ES6:
function uniqBy(a, key) {
var seen = new Set();
return a.filter(item => {
var k = key(item);
return seen.has(k) ? false : seen.add(k);
});
}
(niektórzy wolą !seen.has(k) && seen.add(k)
zamiast seen.has(k) ? false : seen.add(k)
).
Biblioteki
Zarównopodkreślenie jak iLo-Dash zapewniają uniq
metody. Ich algorytmy są zasadniczo podobne do pierwszego fragmentu powyżej i sprowadzają się do tego: {]}
var result = [];
a.forEach(function(item) {
if(result.indexOf(item) < 0) {
result.push(item);
}
});
To jest kwadratowe, ale są fajne dodatkowe gadżety, takie jak zawijanie natywnego indexOf
, zdolność uniqify przez klucz (iteratee
w ich języku) i optymalizacje dla już posortowanych tablice.
Jeśli używasz jQuery i nie możesz znieść niczego bez dolara przed nim, to wygląda to tak:
$.uniqArray = function(a) {
return $.grep(a, function(item, pos) {
return $.inArray(item, a) === pos;
});
}
Który jest, znowu, odmianą pierwszego fragmentu.
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:
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
Ten kawałek brzydkiego kodu robi podobnie jak fragment #3 powyżej, , ale o rząd wielkości szybciej (od 2017 roku jest tylko dwa razy szybciej - rdzeni JS wykonują świetną robotę!)
function uniq(a) {
var seen = {};
return a.filter(function(item) {
return seen.hasOwnProperty(item) ? false : (seen[item] = true);
});
}
function uniq_fast(a) {
var seen = {};
var out = [];
var len = a.length;
var j = 0;
for(var i = 0; i < len; i++) {
var item = a[i];
if(seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
/////
var r = [0,1,2,3,4,5,6,7,8,9],
a = [],
LEN = 1000,
LOOPS = 1000;
while(LEN--)
a = a.concat(r);
var d = new Date();
for(var i = 0; i < LOOPS; i++)
uniq(a);
document.write('<br>uniq, ms/loop: ' + (new Date() - d)/LOOPS)
var d = new Date();
for(var i = 0; i < LOOPS; i++)
uniq_fast(a);
document.write('<br>uniq_fast, ms/loop: ' + (new Date() - d)/LOOPS)
ES6
ES6 dostarcza obiekt Set , co znacznie ułatwia sprawę:
function uniq(a) {
return Array.from(new Set(a));
}
Lub
let uniq = a => [...new Set(a)];
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żywać zestawów od samego początku?
Generatory
Na tej samej podstawie można zbudować "leniwą", opartą na generatorze wersjęuniq
: {]}
- weź następną wartość z argumentu
- jeśli to już było widziane, pomiń to
- w przeciwnym razie, oddaj go i dodaj do zbioru już widzianych wartości
function* uniqIter(a) {
let seen = new Set();
for (let x of a) {
if (!seen.has(x)) {
seen.add(x);
yield x;
}
}
}
// example:
function* randomsBelow(limit) {
while (1)
yield Math.floor(Math.random() * limit);
}
// note that randomsBelow is endless
count = 20;
limit = 30;
for (let r of uniqIter(randomsBelow(limit))) {
console.log(r);
if (--count === 0)
break
}
// exercise for the reader: what happens if we set `limit` less than `count` and why
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-30 23:53:21
Zmęczyło mnie oglądanie wszystkich złych przykładów z for-loopami lub jQuery. Javascript ma do tego idealne narzędzia: sortowanie, mapowanie i redukowanie.
Uniq redukuje przy zachowaniu istniejącego porządku
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
var uniq = names.reduce(function(a,b){
if (a.indexOf(b) < 0 ) a.push(b);
return a;
},[]);
console.log(uniq, names) // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
// one liner
return names.reduce(function(a,b){if(a.indexOf(b)<0)a.push(b);return a;},[]);
Szybsze uniq z sortowaniem
Są prawdopodobnie szybsze sposoby, ale ten jest całkiem przyzwoity.
var uniq = names.slice() // slice makes copy of array before sorting it
.sort(function(a,b){
return a > b;
})
.reduce(function(a,b){
if (a.slice(-1)[0] !== b) a.push(b); // slice(-1)[0] means last item in array without removing it (like .pop())
return a;
},[]); // this empty array becomes the starting value for a
// one liner
return names.slice().sort(function(a,b){return a > b}).reduce(function(a,b){if (a.slice(-1)[0] !== b) a.push(b);return a;},[]);
Aktualizacja 2015: wersja ES6:
W ES6 masz sety i Spread, co sprawia, że bardzo łatwo i wydajnie usuwać wszystkie duplikaty:
var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]
Sortuj na podstawie występowanie:
Ktoś zapytał o uporządkowanie wyników na podstawie ilości unikalnych nazw:
var names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']
var uniq = names
.map((name) => {
return {count: 1, name: name}
})
.reduce((a, b) => {
a[b.name] = (a[b.name] || 0) + b.count
return a
}, {})
var sorted = Object.keys(uniq).sort((a, b) => uniq[a] < uniq[b])
console.log(sorted)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-02 22:08:06
Vanilla JS: Usuń duplikaty za pomocą obiektu takiego jak zbiór
Zawsze możesz spróbować umieścić go w obiekcie, a następnie iterację poprzez jego klucze:
function remove_duplicates(arr) {
var obj = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
obj[arr[i]] = true;
}
for (var key in obj) {
ret_arr.push(key);
}
return ret_arr;
}
Vanilla JS: Usuń duplikaty, śledząc już widziane wartości (porządek-Bezpieczny)
Lub, w przypadku wersji bezpiecznej dla zamówień, użyj obiektu do przechowywania wszystkich wcześniej widzianych wartości i sprawdź wartości przed dodaniem do tablicy.
function remove_duplicates_safe(arr) {
var seen = {};
var ret_arr = [];
for (var i = 0; i < arr.length; i++) {
if (!(arr[i] in seen)) {
ret_arr.push(arr[i]);
seen[arr[i]] = true;
}
}
return ret_arr;
}
ECMAScript 6: użyj nowej struktury danych zestawu (zamówienie-bezpieczne)
ECMAScript 6 dodaje nową strukturę danych Set
, która umożliwia przechowywanie wartości dowolnego typu. Set.values
zwraca elementy w kolejności wstawiania.
function remove_duplicates_es6(arr) {
let s = new Set(arr);
let it = s.values();
return Array.from(it);
}
Przykład użycia:
a = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
b = remove_duplicates(a);
// b:
// ["Adam", "Carl", "Jenny", "Matt", "Mike", "Nancy"]
c = remove_duplicates_safe(a);
// c:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
d = remove_duplicates_es6(a);
// d:
// ["Mike", "Matt", "Nancy", "Adam", "Jenny", "Carl"]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-18 17:11:56
Użyj Podkreślenia.js
To biblioteka z wieloma funkcjami do manipulowania tablicami.
Krawat pasuje do smokingu jQuery 'ego i Backbone' a.js ' s szelki.
_.uniq(array, [isSorted], [iterator])
pseudonim: unique
Tworzy pozbawioną duplikatów wersję tablicy , używając = = = do testowania obiektu równość. Jeśli z góry wiesz, że tablica jest posortowana, przechodząc true dla isSorted uruchomi znacznie szybszy algorytm. Jeśli chcesz Oblicz unikalne przedmioty na podstawie transformacji, przekaż iterator funkcja.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
alert(_.uniq(names, false));
Uwaga: Lo-Dash (An underscore konkurent) oferuje również porównywalne .implementacja uniq .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-10 00:51:22
Wersja jednowierszowa z użyciem filtra tablicy i funkcji indexOf:
arr = arr.filter (function (value, index, array) {
return array.indexOf (value) == index;
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 07:04:26
Możesz to po prostu zrobić w JavaScript, za pomocą drugiego-index-parametru metody filter
:
var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });
Lub w krótkiej dłoni
a.filter((v,i) => a.indexOf(v) == i)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-04 07:10:12
Jedna linia:
let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 01:39:01
Najbardziej zwięzłym sposobem usuwania duplikatów z tablicy przy użyciu natywnych funkcji javascript jest użycie sekwencji jak poniżej:
vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])
Nie ma potrzeby slice
ani indexOf
wewnątrz funkcji reduce, jak widziałem w innych przykładach! warto jednak używać go razem z funkcją filtra:
vals.filter(function(v, i, a){ return i == a.indexOf(v) })
Jeszcze inny sposób działania ES6(2015), który działa już na kilku przeglądarkach, to:
Array.from(new Set(vals))
Lub nawet za pomocą spread operator :
[...new Set(vals)]
Zdrówko!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-14 14:12:57
Użyj
Array.filter()
w ten sposób
var actualArr = ['Apple', 'Apple', 'Banana', 'Mango', 'Strawberry', 'Banana'];
console.log('Actual Array: ' + actualArr);
var filteredArr = actualArr.filter(function(item, index) {
if (actualArr.indexOf(item) == index)
return item;
});
console.log('Filtered Array: ' + filteredArr);
Można to skrócić w ES6 do
actualArr.filter((item,index,self) => self.indexOf(item)==index);
Tutaj jest ładne Wyjaśnienie Array.filter()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-10 09:37:34
Go for this one:
var uniqueArray = duplicateArray.filter(function(elem, pos) {
return duplicateArray.indexOf(elem) == pos;
});
Teraz uniqueArray nie zawiera duplikatów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-19 07:52:17
Najprostszy, na jaki do tej pory wpadłem. W es6.
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl", "Mike", "Nancy"]
var noDupe = Array.from(new Set(names))
Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-25 05:18:30
Zrobiłem szczegółowe porównanie dupes removal w innym pytaniu, ale zauważywszy, że to jest prawdziwe miejsce, chciałem podzielić się nim również tutaj.
Uważam, że jest to najlepszy sposób, aby to zrobić
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = Object.keys(myArray.reduce((p,c) => (p[c] = true,p),{}));
console.log(reduced);
OK .. mimo, że ten jest O(n), A Pozostałe O (N^2) byłem ciekaw, aby zobaczyć porównanie benchmarku między tym reduce / look up table I filter/indexOf combo (wybieram Jeetendras bardzo ładna implementacja https://stackoverflow.com/a/37441144/4543207 ). przygotowuję tablicę 100k pozycji wypełnioną losowymi dodatnimi liczbami w zakresie 0-9999 i usuwa duplikaty. Powtórzę test 10 razy, a średnia z wyników pokazuje, że nie są one zgodne w wydajności.
- w Firefoksie v47 reduce & lut : 14.85 ms vs filter & indexOf: 2836ms
- w chrome v51 reduce & lut : 23.90 ms vs filter & indexOf: 1066ms
var myArray = [100, 200, 100, 200, 100, 100, 200, 200, 200, 200],
reduced = [...myArray.reduce((p,c) => p.set(c,true),new Map()).keys()];
console.log(reduced);
Wow to było krótkie..! Ale co z występem?.? Jest piękny... Ponieważ ciężki ciężar filtra / indexOf podniósł się na nasze ramiona, teraz mogę przetestować tablicę 1m losowych pozycji dodatnich liczb całkowitych w zakresie 0..99999 aby otrzymać średnią z 10 kolejne testy. Mogę powiedzieć, że tym razem to prawdziwy mecz. Zobacz wynik na własne oczy:)
var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 10;
for (var i = 0; i<count; i++){
ranar = (new Array(1000000).fill(true)).map(e => Math.floor(Math.random()*100000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");
Którego byś użył..? Nie tak szybko...! Nie daj się zwieść. / Align = "left" / Spójrz... we wszystkich powyższych przypadkach wypełniamy tablicę wielkości n liczbami z zakresu
var ranar = [],
red1 = a => Object.keys(a.reduce((p,c) => (p[c] = true,p),{})),
red2 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*100000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("reduce & lut took: " + avg1 + "msec");
console.log("map & spread took: " + avg2 + "msec");
Oto spektakularny powrót Map ()..! Może teraz możesz podjąć lepszą decyzję, gdy chcesz usunąć dupki.
Dobrze, wszyscy jesteśmy szczęśliwi. Ale główna rola zawsze jest ostatnia z niektórymi oklaski. Jestem pewien, że niektórzy z was zastanawiają się, co zrobiłby Set object. Skoro jesteśmy otwarci na ES6 i wiemy, że Map jest zwycięzcą poprzednich gier, porównajmy mapę z zestawem jako finał. Typowy mecz Real Madryt vs Barcelona tym razem... a może jest? Zobaczmy kto wygra el classico:)var ranar = [],
red1 = a => reduced = [...a.reduce((p,c) => p.set(c,true),new Map()).keys()],
red2 = a => Array.from(new Set(a)),
avg1 = [],
avg2 = [],
ts = 0,
te = 0,
res1 = [],
res2 = [],
count= 100;
for (var i = 0; i<count; i++){
ranar = (new Array(100000).fill(true)).map(e => Math.floor(Math.random()*10000000));
ts = performance.now();
res1 = red1(ranar);
te = performance.now();
avg1.push(te-ts);
ts = performance.now();
res2 = red2(ranar);
te = performance.now();
avg2.push(te-ts);
}
avg1 = avg1.reduce((p,c) => p+c)/count;
avg2 = avg2.reduce((p,c) => p+c)/count;
console.log("map & spread took: " + avg1 + "msec");
console.log("set & A.from took: " + avg2 + "msec");
Wow.. człowieku..! Niespodziewanie okazało się, że wcale nie jest to el classico. Raczej FC Barcelona przeciwko CA Osasuna:))Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:37
Poniżej jest o ponad 80% szybszy niż metoda jQuery (patrz testy poniżej). Jest to odpowiedź z podobnego pytania sprzed kilku lat. Jeśli natknę się na osobę, która pierwotnie go zaproponowała, wyślę kredyt. Czysty JS.
var temp = {};
for (var i = 0; i < array.length; i++)
temp[array[i]] = true;
var r = [];
for (var k in temp)
r.push(k);
return r;
Moje porównanie przypadków testowych: http://jsperf.com/remove-duplicate-array-tests
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-03 09:56:06
Oto prosta odpowiedź na pytanie.
var names = ["Alex","Tony","James","Suzane", "Marie", "Laurence", "Alex", "Suzane", "Marie", "Marie", "James", "Tony", "Alex"];
var uniqueNames = [];
for(var i in names){
if(uniqueNames.indexOf(names[i]) === -1){
uniqueNames.push(names[i]);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-26 20:26:17
W ECMAScript 6 (aka ECMAScript 2015), Set
może być używany do filtrowania duplikatów. Następnie można ją przekonwertować z powrotem do tablicy za pomocą operatora spreadu .
var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
unique = [...new Set(names)];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-08 12:28:06
Rozwiązanie 1
Array.prototype.unique = function() {
var a = [];
for (i = 0; i < this.length; i++) {
var current = this[i];
if (a.indexOf(current) < 0) a.push(current);
}
return a;
}
Rozwiązanie 2 (za pomocą zestawu)
Array.prototype.unique = function() {
return Array.from(new Set(this));
}
Test
var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]
Wydajność
Kiedy testowałem obie implementacje (z i bez Set) pod kątem wydajności w chrome, stwierdziłem, że ta z Set jest o wiele szybsza!
Array.prototype.unique1 = function() {
var a = [];
for (i = 0; i < this.length; i++) {
var current = this[i];
if (a.indexOf(current) < 0) a.push(current);
}
return a;
}
Array.prototype.unique2 = function() {
return Array.from(new Set(this));
}
var x=[];
for(var i=0;i<10000;i++){
x.push("x"+i);x.push("x"+(i+1));
}
console.time("unique1");
console.log(x.unique1());
console.timeEnd("unique1");
console.time("unique2");
console.log(x.unique2());
console.timeEnd("unique2");
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-25 07:05:48
Prostą, ale skuteczną techniką jest użycie metody filter
w połączeniu z filtrem function(value, index){ return this.indexOf(value) == index }
.
Przykład kodu:
var data = [2,3,4,5,5,4];
var filter = function(value, index){ return this.indexOf(value) == index };
var filteredData = data.filter(filter, data );
document.body.innerHTML = '<pre>' + JSON.stringify(filteredData, null, '\t') + '</pre>';
[[3]}Zobacz this Fiddle.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-29 09:31:39
Najlepsze odpowiedzi mają złożoność O(n²)
, ale można to zrobić za pomocą tylko O(n)
, używając obiektu jako hash:
function getDistinctArray(arr) {
var dups = {};
return arr.filter(function(el) {
var hash = el.valueOf();
var isDup = dups[hash];
dups[hash] = true;
return !isDup;
});
}
To będzie działać dla ciągów, liczb i dat. Jeśli tablica zawiera złożone obiekty (tzn. muszą być porównane z ===
), powyższe rozwiązanie nie zadziała. Można uzyskać implementację O(n)
dla obiektów, ustawiając flagę na samym obiekcie:
function getDistinctObjArray(arr) {
var distinctArr = arr.filter(function(el) {
var isDup = el.inArray;
el.inArray = true;
return !isDup;
});
distinctArr.forEach(function(el) {
delete el.inArray;
});
return distinctArr;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-06 22:32:59
Oto prosta metoda bez żadnych specjalnych bibliotek są specjalne funkcje,
name_list = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];
get_uniq = name_list.filter(function(val,ind) { return name_list.indexOf(val) == ind; })
console.log("Original name list:"+name_list.length, name_list)
console.log("\n Unique name list:"+get_uniq.length, get_uniq)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-03 14:18:30
Poza tym, że jest prostszym, bardziej zwięzłym rozwiązaniem niż obecne odpowiedzi (minus przyszłościowe ES6), przetestowałem to i było znacznie szybsze:
var uniqueArray = dupeArray.filter(function(item, i, self){
return self.lastIndexOf(item) == i;
});
Jedno zastrzeżenie: Array.lastindexof () została dodana w IE9, więc jeśli chcesz przejść niżej, musisz poszukać gdzie indziej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-13 00:46:58
Więc opcje są:
let a = [11,22,11,22];
let b = []
b = [ ...new Set(a) ];
// b = [11, 22]
b = Array.from( new Set(a))
// b = [11, 22]
b = a.filter((val,i)=>{
return a.indexOf(val)==i
})
// b = [11, 22]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-15 14:26:39
Ogólne Podejście Funkcjonalne
[11]}Oto ogólne i ściśle funkcjonalne podejście do ES2015:// small, reusable auxiliary functions
const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const uncurry = f => (a, b) => f(a) (b);
const push = x => xs => (xs.push(x), xs);
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);
const some = f => xs => xs.some(apply(f));
// the actual de-duplicate function
const uniqueBy = f => foldl(
acc => x => some(f(x)) (acc)
? acc
: push(x) (acc)
) ([]);
// comparators
const eq = y => x => x === y;
// string equality case insensitive :D
const seqCI = y => x => x.toLowerCase() === y.toLowerCase();
// mock data
const xs = [1,2,3,1,2,3,4];
const ys = ["a", "b", "c", "A", "B", "C", "D"];
console.log( uniqueBy(eq) (xs) );
console.log( uniqueBy(seqCI) (ys) );
Możemy łatwo wyprowadzić unique
z unqiueBy
lub użyć szybszej implementacji wykorzystując Set
s:
const unqiue = uniqueBy(eq);
// const unique = xs => Array.from(new Set(xs));
Korzyści z tego podejścia:
- rozwiązanie Ogólne za pomocą oddzielnej funkcji komparatora
- deklaratywna i zwięzła implementacja
- ponowne użycie innych małych, ogólnych funkcje
Względy Wydajności
uniqueBy
nie jest tak szybka jak imperatywna implementacja z pętlami, ale jest o wiele bardziej ekspresyjna ze względu na swoją generyczność.
Jeśli zidentyfikujesz uniqueBy
jako przyczynę konkretnej kary za wydajność w aplikacji, zastąp ją zoptymalizowanym kodem. Oznacza to, że najpierw napisz swój kod w funkcjonalny, deklaratywny sposób. Następnie, jeśli napotkasz problemy z wydajnością, spróbuj zoptymalizować kod w lokalizacjach, które są przyczyna problemu.
Zużycie pamięci i wywóz śmieci
uniqueBy
wykorzystuje mutacje (push(x) (acc)
) ukryte w jego ciele. Ponownie wykorzystuje akumulator zamiast wyrzucać go po każdej iteracji. Zmniejsza to zużycie pamięci i ciśnienie GC. Ponieważ ten efekt uboczny jest zawinięty wewnątrz funkcji, wszystko na zewnątrz pozostaje czyste.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-09 08:02:47
$(document).ready(function() {
var arr1=["dog","dog","fish","cat","cat","fish","apple","orange"]
var arr2=["cat","fish","mango","apple"]
var uniquevalue=[];
var seconduniquevalue=[];
var finalarray=[];
$.each(arr1,function(key,value){
if($.inArray (value,uniquevalue) === -1)
{
uniquevalue.push(value)
}
});
$.each(arr2,function(key,value){
if($.inArray (value,seconduniquevalue) === -1)
{
seconduniquevalue.push(value)
}
});
$.each(uniquevalue,function(ikey,ivalue){
$.each(seconduniquevalue,function(ukey,uvalue){
if( ivalue == uvalue)
{
finalarray.push(ivalue);
}
});
});
alert(finalarray);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-15 09:23:48
Tutaj jest bardzo prosty do zrozumienia i pracy w dowolnym miejscu (nawet w PhotoshopScript) kodu. Sprawdź to!
var peoplenames = new Array("Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl");
peoplenames = unique(peoplenames);
alert(peoplenames);
function unique(array){
var len = array.length;
for(var i = 0; i < len; i++) for(var j = i + 1; j < len; j++)
if(array[j] == array[i]){
array.splice(j,1);
j--;
len--;
}
return array;
}
//*result* peoplenames == ["Mike","Matt","Nancy","Adam","Jenny","Carl"]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 17:35:23
for (i=0; i<originalArray.length; i++) {
if (!newArray.includes(originalArray[i])) {
newArray.push(originalArray[i]);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-17 15:39:20
Jest to prawdopodobnie jeden z najszybszych sposobów na trwałe usunięcie duplikatów z tablicy 10x razy szybciej niż większość funkcji tutaj.& 78x szybciej w safari
function toUnique(a,b,c){ //array,placeholder,placeholder
b=a.length;while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
- Test: http://jsperf.com/wgu
- Demo: http://jsfiddle.net/46S7g /
- Więcej: https://stackoverflow.com/a/25082874/2450730
Jeśli nie możesz przeczytać kodu powyżej zapytaj, przeczytaj książkę javascript lub oto kilka wyjaśnień na temat krótszego kodu. https://stackoverflow.com/a/21353032/2450730
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:32
Jeśli przypadkiem używałeś
D3.js
You could do
d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-31 22:38:53
Https://jsfiddle.net/2w0k5tz8/
function remove_duplicates(array_){
var ret_array = new Array();
for (var a = array_.length - 1; a >= 0; a--) {
for (var b = array_.length - 1; b >= 0; b--) {
if(array_[a] == array_[b] && a != b){
delete array_[b];
}
};
if(array_[a] != undefined)
ret_array.push(array_[a]);
};
return ret_array;
}
console.log(remove_duplicates(Array(1,1,1,2,2,2,3,3,3)));
Wykonaj pętlę, Usuń duplikaty i utwórz uchwyt klonowania tablicy, ponieważ indeks tablicy nie będzie aktualizowany.
Pętla do tyłu dla lepszej wydajności (twoja pętla nie będzie musiała sprawdzać długości tablicy)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-18 14:45:30
To było tylko inne rozwiązanie, ale inne niż reszta.
function diffArray(arr1, arr2) {
var newArr = arr1.concat(arr2);
newArr.sort();
var finalArr = [];
for(var i = 0;i<newArr.length;i++) {
if(!(newArr[i] === newArr[i+1] || newArr[i] === newArr[i-1])) {
finalArr.push(newArr[i]);
}
}
return finalArr;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-10 14:23:29