Удалить повторяющиеся значения из массива JS [duplicate]

этот вопрос уже есть ответ здесь:

  • получить все уникальные значения в массиве JavaScript (удалить дубликаты) 59 ответов

У меня есть очень простой массив JavaScript, который может содержать или не содержать дубликаты.

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

Мне нужно удалить дубликаты и поместить уникальные значения в новый матрица.

Я могу указать все коды, которые я пробовал, но я думаю, что это бесполезно, потому что они не работают. Я тоже принимаю решения на jQuery.

аналогичный вопрос:

  • получить все не уникальные значения (т. е.: дублировать/более одного вхождения) в массиве

30 ответов


быстрый и грязный с помощью 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);
});

"умный", но наивный способ

uniqueArray = a.filter(function(item, pos) {
    return a.indexOf(item) == pos;
})

в принципе, мы перебираем массив и для каждого элемента проверяем, равна ли первая позиция этого элемента в массиве текущей позиции. Очевидно, что эти две позиции различны для повторяющихся элементов.

используя 3-й ("этот массив") параметр обратного вызова фильтра, мы можем избежать закрытия переменной массива:

uniqueArray = a.filter(function(item, pos, self) {
    return self.indexOf(item) == pos;
})

хотя краткий, этот алгоритм не особенно эффективен для больших массивов (квадратичное время).

хеш-таблицы к спасению

function uniq(a) {
    var seen = {};
    return a.filter(function(item) {
        return seen.hasOwnProperty(item) ? false : (seen[item] = true);
    });
}

вот как это обычно делается. Идея состоит в том, чтобы поместить каждый элемент в хэш-таблицу, а затем проверить его присутствие мгновенно. Это дает нам линейное время, но имеет как минимум два недостатка:

  • поскольку хэш-ключи могут быть только строками в Javascript, этот код не различает числа и"числовые строки". То есть, uniq([1,"1"]) вернется только [1]
  • по той же причине, все объекты будут считаться равными: uniq([{foo:1},{foo:2}]) вернется только [{foo:1}].

тем не менее, если ваши массивы содержат только примитивы, и вы не заботитесь о типах (например, это всегда числа), это решение является оптимальным.

лучший из двух миров

универсальное решение объединяет оба подхода: оно использует хэш-поиск примитивов и линейный поиск объекты.

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);
    });
}

сортировать / uniq

другой вариант-сначала отсортировать массив, а затем удалить каждый элемент равен предыдущему:

function uniq(a) {
    return a.sort().filter(function(item, pos, ary) {
        return !pos || item != ary[pos - 1];
    })
}

опять же, это не работает с объектами (потому что все объекты равны для sort). Кроме того, мы молча меняем исходный массив в качестве побочного эффекта - не хорошо! Однако, если ваш ввод уже отсортирован ,это путь (просто удалите sort выше).

уникальная от...

иногда желательно унифицировать список на основе некоторых критериев, отличных от равенства, например, отфильтровать объекты, которые отличаются, но имеют некоторое свойство. Это можно сделать элегантно, передав обратный вызов. Этот" ключевой " обратный вызов применяется к каждому элементу, и элементы с равными "ключами" удаляются. С key ожидается возврат примитива, хэш-таблица будет работать нормально здесь:

function uniqBy(a, key) {
    var seen = {};
    return a.filter(function(item) {
        var k = key(item);
        return seen.hasOwnProperty(k) ? false : (seen[k] = true);
    })
}

особенно полезным key() is JSON.stringify который удалит объекты, которые физически отличаются, но "выглядят" одинаково:

a = [[1,2,3], [4,5,6], [1,2,3]]
b = uniqBy(a, JSON.stringify)
console.log(b) // [[1,2,3], [4,5,6]]

если key не примитивно, приходится прибегать к линейному поиску:

function uniqBy(a, key) {
    var index = [];
    return a.filter(function (item) {
        var k = key(item);
        return index.indexOf(k) >= 0 ? false : index.push(k);
    });
}

или использовать Set объект в 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);
    });
}

(некоторые люди предпочитают !seen.has(k) && seen.add(k) вместо seen.has(k) ? false : seen.add(k)).

библиотеки

и подчеркивание и Lo-Dash обеспечить uniq методы. Их алгоритмы в основном похож на первый фрагмент выше и сводится к следующему:

var result = [];
a.forEach(function(item) {
     if(result.indexOf(item) < 0) {
         result.push(item);
     }
});

это квадратично, но есть хорошие дополнительные лакомства, такие как упаковка native indexOf, возможность uniqify ключом (iteratee на их языке) и оптимизации для уже отсортированных массивов.

если вы используете jQuery и не можете ничего вынести без доллара перед ним, он выглядит так:

  $.uniqArray = function(a) {
        return $.grep(a, function(item, pos) {
            return $.inArray(item, a) === pos;
        });
  }

что, опять же, является вариацией первого фрагмент.

производительность

вызовы функций дороги в Javascript, поэтому вышеуказанные решения, как бы лаконичны они ни были, не особенно эффективны. Для максимальной производительности замените filter с циклом и избавиться от других вызовов функций:

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;
}

этот кусок уродливого кода делает то же самое, что и фрагмент #3 выше,но на порядок быстрее (по состоянию на 2017 год это только в два раза быстрее-JS core люди делают большой Иов!)

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)

ЕС6

ЕС6 предоставляет Set "объект", который делает вещи намного проще:

function uniq(a) {
   return Array.from(new Set(a));
}

или

let uniq = a => [...new Set(a)];

обратите внимание, что, в отличие от python, наборы ES6 повторяются в порядке вставки, поэтому этот код сохраняет порядок исходного массива.

однако, если вам нужен массив с уникальными элементами, почему бы не использовать прямо из начало?

генераторы

"ленивый", генератор на основе версии uniq может быть построен на той же основе:

  • берем следующее значение из аргумента
  • если его уже видели, пропустите его
  • в противном случае дайте его и добавьте в набор уже виденных значений

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

устал видеть все плохие примеры с for-loops или jQuery. Javascript имеет идеальные инструменты для этого в настоящее время: сортировка, карта и сокращение.

Uniq уменьшить при сохранении существующего порядка

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;},[]);

быстрее uniq с сортировкой

вероятно, есть более быстрые способы, но этот довольно приличный.

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;},[]);

обновление 2015: ES6 версия:

в ES6 у вас есть наборы и распространение, что делает его очень легким и эффективным для удаления всех дубликаты:

var uniq = [ ...new Set(names) ]; // [ 'Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Carl' ]

сортировка по наступлении:

кто-то спросил о заказе результатов на основе того, сколько уникальных имен есть:

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)

Vanilla JS: удаление дубликатов с помощью объекта, такого как Set

вы всегда можете попробовать поместить его в объект, а затем перебирать его ключи:

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: удалите дубликаты, отслеживая уже увиденные значения (order-safe)

или, для версии order-safe, используйте объект для хранения всех ранее виденных значений и проверьте значения перед добавлением в матрица.

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: Используйте новую структуру данных Set (order-safe)

ECMAScript 6 добавляет новый Set Data-Structure, которая позволяет хранить значения любого типа. Set.values возвращает элементы в порядке вставки.

function remove_duplicates_es6(arr) {
    let s = new Set(arr);
    let it = s.values();
    return Array.from(it);
}

пример использования:

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"]

использовать подчеркивания.js

это библиотека с множеством функций для обработки массивов.

это галстук, чтобы идти вместе с смокингом jQuery и позвоночником.в JS это подвески.

_.uniq

_.uniq(array, [isSorted], [iterator]) псевдоним: уникальный
Производит дубликат-бесплатную версию массив, используя === для проверки объекта равенство. Если вы заранее знаете, что массив сортируется, передает правда на isSorted будет работать гораздо быстрее алгоритма. Если хочешь ... вычислить уникальные элементы на основе преобразования, передать итератор функция.

пример

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"];

alert(_.uniq(names, false));

Примечание: Lo-Dash (an подчеркивание конкурент) также предлагает сопоставимый .uniq реализация.


однострочная версия с использованием фильтра массива и функций indexOf:

arr = arr.filter (function (value, index, array) { 
    return array.indexOf (value) == index;
});

вы можете просто сделать это в JavaScript, с помощью второго-index-параметра filter способ:

var a = [2,3,4,5,5,4];
a.filter(function(value, index){ return a.indexOf(value) == index });

или короче руки

a.filter((v,i) => a.indexOf(v) == i)

одна строка:

let names = ['Mike','Matt','Nancy','Adam','Jenny','Nancy','Carl', 'Nancy'];
let dup = [...new Set(names)];
console.log(dup);

самый краткий способ удалить дубликаты из массива с помощью собственных функций javascript - использовать последовательность, как показано ниже:

vals.sort().reduce(function(a, b){ if (b != a[0]) a.unshift(b); return a }, [])

не нужно slice, ни indexOf в пределах функции уменьшения, как я видел в других примерах! имеет смысл использовать ее вместе с функцией фильтра:

vals.filter(function(v, i, a){ return i == a.indexOf(v) })

еще один способ ES6 (2015) сделать это, который уже работает на нескольких браузерах:

Array.from(new Set(vals))

или даже распространение оператор:

[...new Set(vals)]

ура!


использовать Array.filter() такой

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);

Это можно сделать короче в ES6 до

actualArr.filter((item,index,self) => self.indexOf(item)==index);

здесь хорошее объяснение Array.filter()


пойдите для этого:

var uniqueArray = duplicateArray.filter(function(elem, pos) {
    return duplicateArray.indexOf(elem) == pos;
}); 

теперь uniqueArray не содержит дубликатов.


самый простой, с которым я столкнулся до сих пор. В 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


Я сделал подробное сравнение удаления дураков в каком-то другом вопросе, но, заметив, что это реальное место, я просто хотел поделиться им здесь.

Я считаю, что это лучший способ, чтобы сделать это

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 .. несмотря на то, что это O (n), а другие-O (n^2) , мне было любопытно увидеть эталонное сравнение между этой таблицей reduce / look up и комбинацией filter/indexOf (я выбираю Jeetendras очень приятную реализацию https://stackoverflow.com/a/37441144/4543207). Я готовлю массив элементов 100K, заполненный случайными целыми положительными числами в диапазоне 0-9999, и он удаляет дубликаты. Я повторяю тест 10 раз, и в среднем результаты показывают, что они не соответствуют производительности.

  • в firefox v47 уменьшить & lut: 14.85 ms vs фильтр & indexOf: 2836ms
  • в chrome v51 уменьшите & lut: 23.90 ms против фильтра & indexOf: 1066ms

Ну пока все хорошо. Но давайте сделаем это правильно на этот раз в стиле ES6. Выглядит так круто..! Но на данный момент, как он будет работать против мощного решения lut, для меня загадка. Позволяет сначала увидеть код,а затем проверить его.

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);

Вау, это было коротким..! Но как насчет спектакля?.? Это прекрасно... Поскольку тяжелый вес фильтра / indexOf поднят над нашими плечами, теперь я могу проверить массив 1M случайных элементов положительных целых чисел в диапазоне 0..99999, чтобы получить в среднем от 10 последовательных тестов. Я могу сказать, что на этот раз это настоящий матч. Смотрите результат сами:)

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");

какой из них вы бы использовали..? Ну не так быстро...! Не обманывайтесь. Карты смещения. Теперь смотреть... во всех вышеперечисленных случаях мы заполняем массив размера n номерами диапазона

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");

теперь это впечатляющее возвращение Map ()..! Может быть, теперь вы можете принять лучшее решение, когда хотите удалить дураков.

Ну ок теперь мы все счастливы. Но главная роль всегда заканчивается аплодисментами. Я уверен, некоторые из вас задаются вопросом, что будет делать Set object. Теперь, когда мы открыты для ES6 и знаем, что Map является победителем предыдущих игр, давайте сравним карту с Set в качестве финала. Типичный Реал игре против Барселоны на этот раз... или нет? Посмотрим, кто выиграет 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");

Вау.. мужчина..! Ну, неожиданно оказалось, что это вовсе не el classico. Больше похоже на ФК Барселона против ка Осасуна :))


следующее более чем на 80% быстрее, чем указанный метод jQuery (см. тесты ниже). Это ответ на аналогичный вопрос несколько лет назад. Если я столкнусь с человеком, который первоначально предложил его, я буду размещать кредит. Чистый 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;

мое сравнение теста : http://jsperf.com/remove-duplicate-array-tests


вот простой ответ на вопрос.

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]);
        }
    }

в ECMAScript 6 (он же ECMAScript 2015), Set может использоваться для фильтрации дубликатов. Затем его можно преобразовать обратно в массив с помощью распространение оператор.

var names = ["Mike","Matt","Nancy","Adam","Jenny","Nancy","Carl"],
    unique = [...new Set(names)];

Решение 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;
}

решение 2 (с помощью Set)

Array.prototype.unique = function() {
    return Array.from(new Set(this));
}

тест

var x=[1,2,3,3,2,1];
x.unique() //[1,2,3]

производительность

когда я тестировал обе реализации (С и без набора) для производительности в chrome, я обнаружил, что один с набором намного быстрее!

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");

простой, но эффективный метод, заключается в использовании filter метод в сочетании с фильтром function(value, index){ return this.indexOf(value) == index }.

пример кода :

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>';

см. также эта скрипка.


верхние ответы имеют сложность O(n²), но это можно сделать только с помощью O(n) используя объект в качестве хэша:

function getDistinctArray(arr) {
    var dups = {};
    return arr.filter(function(el) {
        var hash = el.valueOf();
        var isDup = dups[hash];
        dups[hash] = true;
        return !isDup;
    });
}

это будет работать для строк, чисел и дат. Если Ваш массив содержит сложные объекты (т. е. их нужно сравнить с ===), вышеуказанное решение не будет работать. Вы можете получить O(n) реализация для объектов путем установки флага на самом объекте:

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;
}

вот простой метод без каких-либо специальных библиотек-это специальная функция,

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)

enter image description here


помимо того, что это более простое, более краткое решение, чем текущие ответы (минус будущие ES6), я проверил это, и это было намного быстрее:

var uniqueArray = dupeArray.filter(function(item, i, self){
  return self.lastIndexOf(item) == i;
});

одно предостережение: массив.lastIndexOf () был добавлен в IE9, поэтому, если вам нужно пойти ниже, вам нужно будет искать в другом месте.


таким образом, параметры:

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]

Универсальный Функциональный Подход

вот общий и строго функциональный подход с 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) );

мы можем легко вывести unique С unqiueBy или использовать более быструю реализацию, используя Sets:

const unqiue = uniqueBy(eq);

// const unique = xs => Array.from(new Set(xs));

преимущества такого подхода:

  • универсальное решение с помощью отдельной функции компаратора
  • декларативный и лаконичное реализация
  • повторное использование других небольших общих функций

Производительности

uniqueBy не так быстро, как императивная реализация с циклами, но она более выразительна из-за ее универсальности.

если вы отождествляете uniqueBy в качестве причины конкретного штрафа за производительность в вашем приложении замените его оптимизированным кодом. То есть сначала напишите свой код функциональным, декларативным способом. После этого, при условии, что вы возникнуть проблемы с производительностью, попробуйте оптимизировать код в местах, которые являются причиной проблемы.

потребление памяти и сбор мусора

uniqueBy использует мутации (push(x) (acc)) спрятанный внутри своего тела. Он повторно использует аккумулятор вместо того, чтобы выбрасывать его после каждой итерации. Это уменьшает потребление памяти и давление GC. Поскольку этот побочный эффект обернут внутри функции, все снаружи остается чистым.


$(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);
});

здесь очень просто для понимания и работы в любом месте (даже в PhotoshopScript) кода. Проверьте это!

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"]

for (i=0; i<originalArray.length; i++) {  
    if (!newArray.includes(originalArray[i])) {
        newArray.push(originalArray[i]); 
    }
}

это, вероятно, один из самых быстрых способов навсегда удалить дубликаты из массива В 10 раз быстрее, чем большинство функций здесь.& 78x быстрее в 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. тест:http://jsperf.com/wgu
  2. демо:http://jsfiddle.net/46S7g/
  3. еще:https://stackoverflow.com/a/25082874/2450730

Если вы не можете прочитать код выше задать, читать javascript книга или вот некоторые объяснения о более коротком коде. https://stackoverflow.com/a/21353032/2450730


Если вы используете

D3.js

вы могли бы сделать

d3.set(["foo", "bar", "foo", "baz"]).values() ==> ["foo", "bar", "baz"]

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


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)));

выполните цикл, удалите дубликаты и создайте держатель места массива клонирования, потому что индекс массива не будет обновлен.

цикл назад для лучшей производительности (вашему циклу не нужно будет продолжать проверять длину вашего массива)


Это было просто другое решение, но отличное от остальных.

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;
}