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:

Author: John Slegers, 2012-02-10

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);
});
 381
Author: Roman Bataev,
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
 2342
Author: georg,
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)
 276
Author: Christian Landgren,
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"]
 78
Author: Darthfett,
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

_.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.

Przykład

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 .

 69
Author: Brandon Boone,
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;
});
 62
Author: HBP,
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)
 47
Author: Ashutosh Jha,
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);
 34
Author: tonkihonks13,
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!
 30
Author: Ivo,
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()

 20
Author: Sumit Joshi,
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.

 19
Author: Juhan,
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

 17
Author: Deke,
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
Na razie dobrze. Ale niech zrób to poprawnie tym razem w stylu ES6. Wygląda super..! Ale jak na razie to, jak będzie działać przeciwko potężnemu rozwiązaniu lut, jest dla mnie tajemnicą. Pozwala najpierw zobaczyć kod, a następnie porównać go.

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:))
 16
Author: Redu,
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

 14
Author: Levi,
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]);
        }
    }
 13
Author: drew7721,
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)];
 13
Author: Oriol,
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");
 12
Author: ShAkKiR,
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.
 10
Author: John Slegers,
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;
}
 9
Author: gilly3,
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)

Tutaj wpisz opis obrazka

 9
Author: Mohideen ibn Mohammed,
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.

 8
Author: csuwldcat,
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]
 8
Author: ofir_aghai,
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.

 7
Author: ftor,
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);
});
 4
Author: user3840178,
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"]
 4
Author: bodich,
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]); 
    }
}
 4
Author: MBJH,
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)
}
  1. Test: http://jsperf.com/wgu
  2. Demo: http://jsfiddle.net/46S7g /
  3. 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

 3
Author: cocco,
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"]

Https://github.com/mbostock/d3/wiki/Arrays#set_values

 3
Author: jetpackdata.com,
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)

 3
Author: THE AMAZING,
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;
}
 3
Author: Isaac Pak,
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