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

418

Мне нужно проверить массив JavaScript, чтобы увидеть, есть ли какие-либо дубликаты значений. Какой самый простой способ сделать это? Мне просто нужно найти дубликаты значений - мне не нужны их индексы или сколько раз они дублируются.

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

Подобный вопрос:

Скотт Сондерс
источник
22
Кажется, существуют годы путаницы в отношении того, что задает этот вопрос. Мне нужно было знать, какие элементы в массиве были продублированы: «Мне просто нужно найти дублирующиеся значения». Правильный ответ НЕ должен удалять дубликаты из массива. Это обратное тому, что я хотел: список дубликатов, а не список уникальных элементов.
Скотт Сондерс

Ответы:

302

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

const findDuplicates = (arr) => {
  let sorted_arr = arr.slice().sort(); // You can define the comparing function here. 
  // JS by default uses a crappy string compare.
  // (we use slice to clone the array so the
  // original array won't be modified)
  let results = [];
  for (let i = 0; i < sorted_arr.length - 1; i++) {
    if (sorted_arr[i + 1] == sorted_arr[i]) {
      results.push(sorted_arr[i]);
    }
  }
  return results;
}

let duplicatedArray = [9, 9, 111, 2, 3, 4, 4, 5, 7];
console.log(`The duplicates in ${duplicatedArray} are ${findDuplicates(duplicatedArray)}`);

В случае, если вы хотите вернуть как функцию для дубликатов. Это для аналогичного типа случая.

Ссылка: https://stackoverflow.com/a/57532964/8119511

swilliams
источник
10
Msgstr "Если ваш алгоритм сортировки хорош, это должно быть меньше, чем O ^ 2". В частности, это может быть O (n * log (n)).
ESRogs
83
Этот скрипт не работает так хорошо с более чем 2 -х дубликатах (напримерarr = [9, 9, 9, 111, 2, 3, 3, 3, 4, 4, 5, 7];
Mottie
7
@swilliams Я не думаю, что эти рекомендации говорят о том, что вы не используете i++. Вместо этого они говорят не писать j = i + +j. Две разные вещи ИМХО. Я думаю, что i += 1это больше сбивает с толку, чем просто и красиво i++:)
Данило Барген
34
-1 Этот ответ неверен на многих уровнях. Во-первых var sorted_arr = arr.sort(), бесполезно: arr.sort()изменяет исходный массив (что само по себе является проблемой). Это также отбрасывает элемент. (Запустите приведенный выше код. Что происходит с 9?) Cc @dystroy Более чистое решение будетresults = arr.filter(function(elem, pos) { return arr.indexOf(elem) == pos; })
NullUserException
24
Все: вопрос просит отобразить дублирующиеся значения, а не удалять их. Пожалуйста, не редактируйте / не нарушайте код, чтобы попытаться заставить его делать то, чего он не пытается. В предупреждении должны отображаться дублированные значения.
Скотт Сондерс
205

Если вы хотите выявить дубликаты, попробуйте это отличное решение:

function eliminateDuplicates(arr) {
  var i,
      len = arr.length,
      out = [],
      obj = {};

  for (i = 0; i < len; i++) {
    obj[arr[i]] = 0;
  }
  for (i in obj) {
    out.push(i);
  }
  return out;
}

Источник: http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/

rapfaria
источник
18
Это хороший код, но, к сожалению, он не делает то, что я прошу.
Скотт Сондерс
67
Приведенный выше код (мой - это мой блог) довольно близко знакомит вас. Небольшой твик и ты там. Прежде всего, вы можете увидеть, если arr.length и out.length одинаковы. Если они одинаковые, дублированных элементов нет. Но вы хотите немного больше. Если вы хотите «поймать» дубликаты по мере их появления, проверьте, увеличивается ли длина массива после строки obj [arr [i]] = 0. Отличная, а? :-) Спасибо за приятные слова, Рафаэль Монтанаро.
Носредна
6
@MarcoDemaio: Нет, почему код не работает с пробелами? Вы можете поместить все, что вам нравится, в имя свойства - просто не можете использовать точечный синтаксис для доступа к тем, у которых есть пробелы (и не использовать другие символы, которые могут нарушить синтаксический анализ).
Gijs
4
@Gijs: +1 ты прав. Я этого не знал. Но это все еще не работает, когда это массив объектов.
Марко Демайо
3
Этот алгоритм также имеет побочный эффект возврата отсортированного массива, который может быть не тем, что вы хотите.
асимметричный
166

Это мой ответ из дубликата темы (!):

При написании этой записи 2014 - все примеры были for-loop или jQuery. Javascript имеет идеальные инструменты для этого: сортировать, отображать и уменьшать.

Найти дубликаты

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 duplicates = Object.keys(uniq).filter((a) => uniq[a] > 1)

console.log(duplicates) // [ 'Nancy' ]

Более функциональный синтаксис:

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

const names = ['Mike', 'Matt', 'Nancy', 'Adam', 'Jenny', 'Nancy', 'Carl']

const count = names =>
  names.reduce((a, b) => ({ ...a,
    [b]: (a[b] || 0) + 1
  }), {}) // don't forget to initialize the accumulator

const duplicates = dict =>
  Object.keys(dict).filter((a) => dict[a] > 1)

console.log(count(names)) // { Mike: 1, Matt: 1, Nancy: 2, Adam: 1, Jenny: 1, Carl: 1 }
console.log(duplicates(count(names))) // [ 'Nancy' ]

Кристиан Ландгрен
источник
1
Это то решение, которое я искал. Если бы я хотел иметь дюжину циклов for, это было бы довольно легко написать. Ключевое слово в ОП было «эффективным».
Джош
@ChristianLandgren, где объявлена ​​переменная 'dict'? может быть, вместо этого следует использовать 'count'?
Дмитрий Лаптин
4
Пожалуйста, сохраняйте свое вводящее в заблуждение мнение для себя (-1 за наглость). Я лично устал от людей, которые путают «короткие» и «эффективные» и публикуют однострочники, не ставя под сомнение выступления. Короткие программы и современные JS НЕ лучше от природы. Типичное неправильное использование слова «эффективный» здесь . Типичная наивная вера здесь (читай следующие комментарии). Демо здесь .
лист
1
@leaf - оставляйте свои предложения на свои ответы. Решение, которое вы отредактировали, не читабельно, оно может быть производительным (вероятно, нет), но даже в этом случае - на мой взгляд, читаемость часто важнее производительности. Но самое главное - не удаляйте чужой код, чтобы заменить его своим без причины.
Кристиан Ландгрен
1
Разные ответы, да, разные мнения, я так не думаю.
лист
64

Найти повторяющиеся значения в массиве

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

var input = [1, 2, 3, 1, 3, 1];

var duplicates = input.reduce(function(acc, el, i, arr) {
  if (arr.indexOf(el) !== i && acc.indexOf(el) < 0) acc.push(el); return acc;
}, []);

document.write(duplicates); // = 1,3 (actual array == [1, 3])

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

Из-за lower () и indexOf () ему нужен как минимум IE 9.

грипп
источник
7
ES6 arrow / простая / чистая версия:const dupes = items.reduce((acc, v, i, arr) => arr.indexOf(v) !== i && acc.indexOf(v) === -1 ? acc.concat(v) : acc, [])
ZephDavies
30

Вы можете добавить эту функцию или настроить ее и добавить в прототип Javascript Array:

Array.prototype.unique = function () {
    var r = new Array();
    o:for(var i = 0, n = this.length; i < n; i++)
    {
        for(var x = 0, y = r.length; x < y; x++)
        {
            if(r[x]==this[i])
            {
                alert('this is a DUPE!');
                continue o;
            }
        }
        r[r.length] = this[i];
    }
    return r;
}

var arr = [1,2,2,3,3,4,5,6,2,3,7,8,5,9];
var unique = arr.unique();
alert(unique);
karim79
источник
Это лучшее решение, но будьте осторожны при добавлении его в прототип массива, так как это приведет к путанице в IE при переборе значений.
Сампса Суонинен
Perl @RoyTinker также поддерживает их, но я понятия не имел, javascript сделал
Люк H
1
Не выполняет то, о чем просил ФП, возвращает дубликаты.
RWC
27

ОБНОВЛЕНО: ниже используется оптимизированная комбинированная стратегия. Он оптимизирует поиск примитивов, чтобы получить выгоду от времени поиска в хеше O (1) ( uniqueдля массива примитивов используется O (n)). Поиск объектов оптимизируется путем тегирования объектов с уникальным идентификатором при выполнении итерации, поэтому идентификация дублированных объектов также составляет O (1) для каждого элемента и O (n) для всего списка. Единственное исключение - элементы, которые заморожены, но они редки, и резерв предоставляется с использованием массива и indexOf.

var unique = function(){
  var hasOwn = {}.hasOwnProperty,
      toString = {}.toString,
      uids = {};

  function uid(){
    var key = Math.random().toString(36).slice(2);
    return key in uids ? uid() : uids[key] = key;
  }

  function unique(array){
    var strings = {}, numbers = {}, others = {},
        tagged = [], failed = [],
        count = 0, i = array.length,
        item, type;

    var id = uid();

    while (i--) {
      item = array[i];
      type = typeof item;
      if (item == null || type !== 'object' && type !== 'function') {
        // primitive
        switch (type) {
          case 'string': strings[item] = true; break;
          case 'number': numbers[item] = true; break;
          default: others[item] = item; break;
        }
      } else {
        // object
        if (!hasOwn.call(item, id)) {
          try {
            item[id] = true;
            tagged[count++] = item;
          } catch (e){
            if (failed.indexOf(item) === -1)
              failed[failed.length] = item;
          }
        }
      }
    }

    // remove the tags
    while (count--)
      delete tagged[count][id];

    tagged = tagged.concat(failed);
    count = tagged.length;

    // append primitives to results
    for (i in strings)
      if (hasOwn.call(strings, i))
        tagged[count++] = i;

    for (i in numbers)
      if (hasOwn.call(numbers, i))
        tagged[count++] = +i;

    for (i in others)
      if (hasOwn.call(others, i))
        tagged[count++] = others[i];

    return tagged;
  }

  return unique;
}();

Если у вас есть доступные коллекции ES6, то существует гораздо более простая и значительно более быстрая версия. (шим для IE9 + и других браузеров здесь: https://github.com/Benvie/ES6-Harmony-Collections-Shim )

function unique(array){
  var seen = new Set;
  return array.filter(function(item){
    if (!seen.has(item)) {
      seen.add(item);
      return true;
    }
  });
}

источник
действительно? зачем отвечать на вопрос, который был решен более 2 лет назад?
Рене Пот
3
Я отвечал на другой вопрос и, по-видимому, случайно нажал на кого-то, связавшегося с ним, назвав его дубликатом, и в итоге клонировал мой ответ и запутал себя до чертиков. Я много редактирую свои вещи.
16
Я думаю, что это хорошо с разными решениями. Неважно, что тема старая и решаемая, поскольку все еще можно придумать разные способы сделать это. Это типичная проблема в информатике.
Эмиль Викстрем
Вы можете упомянуть, что это основано на методах массива ES5, которые не реализованы в IE <9.
Тим Даун
24

ОБНОВЛЕНО: Короткий однострочный, чтобы получить дубликаты:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) !== i) // [2, 4]

Чтобы получить массив без дубликатов, просто инвертируйте условие:

[1, 2, 2, 4, 3, 4].filter((e, i, a) => a.indexOf(e) === i) // [1, 2, 3, 4]

Я просто не задумывался filter()в своем старом ответе ниже;)


Когда все, что вам нужно, это проверить, что нет дубликатов, как задано в этом вопросе, вы можете использовать every()метод:

[1, 2, 3].every((e, i, a) => a.indexOf(e) === i) // true

[1, 2, 1].every((e, i, a) => a.indexOf(e) === i) // false

Обратите внимание, что every()не работает для IE 8 и ниже.

Лоран Пайо
источник
1
Не выполняет то, о чем просил ФП, возвращает дубликаты.
RWC
Правда, я обновил свой ответ, чтобы исправить это.
Лоран Пайот
Королевское решение! Thnaks
Джереми Пьедноэль
21
var a = ["a","a","b","c","c"];

a.filter(function(value,index,self){ return (self.indexOf(value) !== index )})
Анхель Дэвид Кальдераро Паксиотт
источник
Кажется, это работает, но вам, вероятно, следует включить текст, описывающий, как это работает.
Жнец DIMM
1
Не будет работать, если есть более 2 повторяющихся значений.
Васа
1
Это элегантно и просто. Я люблю это. Для тех, кто хочет понять, как они работают, я создал суть, показывающую, как показывать дубликаты и удалять дубликаты. Смотрите здесь: gist.github.com/jbcoder/f1c616a32ee4d642691792eebdc4257b
Джош,
@TheDIMMReaper для второго 'a'в массиве, внутри функции фильтра the index == 1, тогда какself.indexOf('a') == 0
Сергей Островский
19

Это должно дать вам то, что вы хотите, просто дубликаты.

function find_duplicates(arr) {
  var len=arr.length,
      out=[],
      counts={};

  for (var i=0;i<len;i++) {
    var item = arr[i];
    counts[item] = counts[item] >= 1 ? counts[item] + 1 : 1;
    if (counts[item] === 2) {
      out.push(item);
    }
  }

  return out;
}

find_duplicates(['one',2,3,4,4,4,5,6,7,7,7,'pig','one']); // -> ['one',4,7] in no particular order.
Дэниэл Бердсли
источник
13

используя underscore.js

function hasDuplicate(arr){
    return (arr.length != _.uniq(arr).length);
}
Марко Аллори
источник
9

ES2015

//          🚩🚩   🚩                 🚩 
var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,22],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    unique;

// Combine all the arrays to a single one
unique = arr.concat(arr2, arr3)

// create a new (dirty) Array with only the unique items
unique = unique.map((item,i) => unique.includes(item, i+1) ? item : '' )

// Cleanup - remove duplicate & empty items items 
unique = [...new Set(unique)].filter(n => n)

console.log(unique)


Найти уникальные значения из 3-х массивов (или более):

Array.prototype.unique = function () {
    var arr = this.sort(), i; // input must be sorted for this to work
    for( i=arr.length; i--; )
      arr[i] === arr[i-1] && arr.splice(i,1); // remove duplicate item

    return arr;
}

var arr =  [1,2,2,3,3,4,5,6,2,3,7,8,5,9],
    arr2 = [1,2,511,12,50],
    arr3 = [22],
    // merge arrays & call custom Array Prototype - "unique"
    unique = arr.concat(arr2, arr3).unique();

console.log(unique);  // [22, 50, 12, 511, 2, 1, 9, 5, 8, 7, 3, 6, 4]

Просто полифил для массива indexOf для старых браузеров:

if (!Array.prototype.indexOf){
   Array.prototype.indexOf = function(elt /*, from*/){
     var len = this.length >>> 0;

     var from = Number(arguments[1]) || 0;
     from = (from < 0) ? Math.ceil(from) : Math.floor(from);
     if (from < 0)
        from += len;

     for (; from < len; from++){
        if (from in this && this[from] === elt)
           return from;
     }
     return -1;
  };
}

Решение jQuery с использованием "inArray":

if( $.inArray(this[i], arr) == -1 )

вместо добавления Array.prototype.indexOf

VSync
источник
+1, потому что это определенно более читабельный код, использующий Array.indexOf, но, к сожалению, он кажется медленнее, чем простой вложенный цикл. Даже в браузерах, которые реализуют Array.indexOf наивно, как FF. Плз, посмотрите на эти тесты, которые я сделал здесь: jsperf.com/array-unique2 и дайте мне знать ваши мысли.
Марко Демайо
@shekhardesigner - обновленный ответ. «r» - это массив, в котором вы ищите
vsync
@vsync Мне пришлось инициализировать, var r = [];чтобы ваш код работал. И работал как шарм.
Шехар К. Шарма
@shekhardesigner - извините за смесь, для решения Array Prototype вам не нужна rпеременная
vsync
2
Не выполняет то, о чем просил ФП, возвращает дубликаты.
RWC
8

Вот мое простое и однострочное решение.

Сначала он ищет не уникальные элементы, а затем делает найденный массив уникальным с помощью Set.

Таким образом, у нас есть массив дубликатов в конце.

var array = [1, 2, 2, 3, 3, 4, 5, 6, 2, 3, 7, 8, 5, 22, 1, 2, 511, 12, 50, 22];

console.log([...new Set(
  array.filter((value, index, self) => self.indexOf(value) !== index))]
);

Олег Абражаев
источник
7

Это мое предложение (ES6):

let a = [1, 2, 3, 4, 2, 2, 4, 1, 5, 6]
let b = [...new Set(a.sort().filter((o, i) => o !== undefined && a[i + 1] !== undefined && o === a[i + 1]))]

// b is now [1, 2, 4]
lukaszkups
источник
1
Это сообщит, что единственное вхождение undefinedявляется дубликатом.
Дем Пилафян
1
@DemPilafian спасибо, обновлено
lukaszkups
6
var a = [324,3,32,5,52,2100,1,20,2,3,3,2,2,2,1,1,1].sort();
a.filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});

или при добавлении в prototyp.chain массива

//copy and paste: without error handling
Array.prototype.unique = 
   function(){return this.sort().filter(function(v,i,o){return i&&v!==o[i-1]?v:0;});}

Смотрите здесь: https://gist.github.com/1305056

Лоренц Ло Зауэр
источник
1
Функция фильтра должна возвращать true или false, а не сам элемент. Фильтрация массива, содержащего 0, не вернула бы их.
Мфлодин
Кроме того, я предполагаю, что i&&это позволяет избежать выхода за пределы массива, но это также означает, что первый элемент в отсортированном массиве не будет включен. В вашем примере нет 1в результирующем массиве. Т.е. return i&&v!==o[i-1]?v:0;должно бытьreturn v!==o[i-1];
мфлодин
6

Быстрый и элегантный способ с использованием деструктурирования и уменьшения объектов es6

Он выполняется в O (n) (1 итерация по массиву) и не повторяет значения, которые появляются более 2 раз

const arr = ['hi', 'hi', 'hi', 'bye', 'bye', 'asd']
const {
  dup
} = arr.reduce(
  (acc, curr) => {
    acc.items[curr] = acc.items[curr] ? acc.items[curr] += 1 : 1
    if (acc.items[curr] === 2) acc.dup.push(curr)
    return acc
  }, {
    items: {},
    dup: []
  },
)

console.log(dup)
// ['hi', 'bye']

Лукас Джанон
источник
5

Вот самое простое решение, которое я мог придумать:

    const arr = [-1, 2, 2, 2, 0, 0, 0, 500, -1, 'a', 'a', 'a']

    const filtered = arr.filter((el, index) => arr.indexOf(el) !== index)
    // => filtered = [ 2, 2, 0, 0, -1, 'a', 'a' ]

    const duplicates = [...new Set(filtered)]

    console.log(duplicates)
    // => [ 2, 0, -1, 'a' ]

Вот и все.

Замечания:

  1. Он работает с любыми номерами , включая 0, строки и отрицательные числа например -1- родственный вопрос: Получить все уникальные значения в массиве JavaScript (удаление дубликаты)

  2. Исходный массив arrсохраняется ( filterвозвращает новый массив вместо изменения исходного)

  3. filteredМассив содержит все дубликаты; он также может содержать более 1 одинакового значения (например, наш фильтрованный массив здесь [ 2, 2, 0, 0, -1, 'a', 'a' ])

  4. Если вы хотите получить только дублирующиеся значения (вы не хотите иметь несколько дубликатов с одним и тем же значением), вы можете использовать [...new Set(filtered)](в ES6 есть объект Set, который может хранить только уникальные значения)

Надеюсь это поможет.

Никола Йованович
источник
5

Самый короткий ванильный JS :

[1,1,2,2,2,3].filter((v,i,a) => a.indexOf(v) !== i) // [1, 2, 2]
цыплята
источник
4

Вот очень легкий и простой способ:

var codes = dc_1.split(',');
var i = codes.length;
while (i--) {
  if (codes.indexOf(codes[i]) != i) {
    codes.splice(i,1);
  }
}
Брэндон Феррара
источник
Лучший ответ. И если пользователь хочет получить массив повторяющихся элементов, для этого я обновил @brandon code var i = codes .length; var duplicate = []; while (i--) {if (codes .indexOf (codes [i])! = i) {if (duplicate.indexOf (codes [i]) === -1) {duplicate.push (arr [i]) ; } codes.splice (i, 1); }}
Химаншу Шекхар
4

С ES6 (или с помощью Babel или Typescipt) вы можете просто сделать:

var duplicates = myArray.filter(i => myArray.filter(ii => ii === i).length > 1);

https://es6console.com/j58euhbt/

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

Простой код с синтаксисом ES6 (возврат отсортированного массива дубликатов):

let duplicates = a => {d=[]; a.sort((a,b) => a-b).reduce((a,b)=>{a==b&&!d.includes(a)&&d.push(a); return b}); return d};

Как пользоваться:

duplicates([1,2,3,10,10,2,3,3,10]);
гость
источник
1
.filter () было бы намного проще
Токвиль
4

один лайнер

var arr = [9,1,2,4,3,4,9]
console.log(arr.filter((ele,indx)=>indx!==arr.indexOf(ele))) //get the duplicates
console.log(arr.filter((ele,indx)=>indx===arr.indexOf(ele))) //remove the duplicates

шраван ганджи
источник
что делает indx!для первого примера?
saylestyler
1
@saylestyler Хе-хе, это означает indx !== ...- строгое неравенство.
Дарья
добавление только для массива объектовresult.filter((ele,indx) => indx !== result.map(e => e.name).indexOf(ele.name));
x-magix
4

Этот ответ также может быть полезен, он использует reduce оператор / метод js для удаления дубликатов из массива.

const result = [1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], []);

console.log(result);

Дивьяншу Рават
источник
3
теперь мы можем просто сделать, new Set([1, 2, 2, 3, 3, 3, 3])чтобы удалить дубликаты
Кимбауди
3

Следующая функция (уже упоминавшаяся разновидность функции deleDuplicates), похоже, добилась цели, возвращая test2,1,7,5 для ввода ["test", "test2", "test2", 1, 1, 1, 2 , 3, 4, 5, 6, 7, 7, 10, 22, 43, 1, 5, 8]

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

Эта конкретная реализация работает для (как минимум) строк и чисел.

function findDuplicates(arr) {
    var i,
        len=arr.length,
        out=[],
        obj={};

    for (i=0;i<len;i++) {
        if (obj[arr[i]] != null) {
            if (!obj[arr[i]]) {
                out.push(arr[i]);
                obj[arr[i]] = 1;
            }
        } else {
            obj[arr[i]] = 0;            
        }
    }
    return out;
}
Nosredna
источник
3

Только ES5 (т. Е. Ему необходим polyfill для filter () для IE8 и ниже):

var arrayToFilter = [ 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3 ];

arrayToFilter.
    sort().
    filter( function(me,i,arr){
       return (i===0) || ( me !== arr[i-1] );
    });
gotofritz
источник
Мне нравится это простое решение. Если вы хотите дубликаты, вам нужно сначала найти эти дубликаты, а затем сделать список дубликатов уникальным. [0, 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3] .sort (). Filter (function (me, i, arr) {return (i! == 0 ) && (me == arr [i-1]);}). filter (function (me, i, arr) {return (i === 0) || (me! == arr [i-1]) ;});
Грег
3

var arr = [2, 1, 2, 2, 4, 4, 2, 5];

function returnDuplicates(arr) {
  return arr.reduce(function(dupes, val, i) {
    if (arr.indexOf(val) !== i && dupes.indexOf(val) === -1) {
      dupes.push(val);
    }
    return dupes;
  }, []);
}

alert(returnDuplicates(arr));

Эта функция избегает шага сортировки и использует метод redu () для отправки дубликатов в новый массив, если он еще не существует в нем.

васа
источник
3

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

function toUnique(a,b,c){//array,placeholder,placeholder
 b=a.length;
 while(c=--b)while(c--)a[b]!==a[c]||a.splice(c,1)
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];
toUnique(array);
console.log(array);
  1. Тестовое задание: http://jsperf.com/wgu
  2. Демо-версия: http://jsfiddle.net/46S7g/
  3. Больше: https://stackoverflow.com/a/25082874/2450730

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

РЕДАКТИРОВАТЬ Как указано в комментариях, эта функция возвращает массив с уникальными значениями, однако вопрос требует найти дубликаты. в этом случае простая модификация этой функции позволяет помещать дубликаты в массив, а затем использование предыдущей функции toUniqueудаляет дубликаты дубликатов.

function theDuplicates(a,b,c,d){//array,placeholder,placeholder
 b=a.length,d=[];
 while(c=--b)while(c--)a[b]!==a[c]||d.push(a.splice(c,1))
}
var array=[1,2,3,4,5,6,7,8,9,0,1,2,1];

toUnique(theDuplicates(array));
кокко
источник
7
«если вы не можете прочитать приведенный выше код, спросите, прочитайте книгу по javascript» В этом ответе слишком много кода для гольфа. Имена переменных, такие как a, b, c, затрудняют чтение кода. Отказ от фигурных скобок делает его еще хуже.
Ривер-Клер Уильямсон
Большинство моих ответов основаны на производительности и экономии места (другие решения уже опубликованы) ... если вам не нравится понизить голосование ... еще изучите javascript, прочитайте книгу js ... или используйте jquery ... они есть много ответов, если вы ищете простое решение. Если вы действительно хотите чему-то научиться, я с удовольствием объясню кодовую букву за буквой. Поскольку я не вижу реального вопроса в вашем комментарии, я думаю, вы просто ищете мотив, чтобы понизить мой ответ ... продолжайте ... у меня нет проблем с этим. Задайте реальный вопрос или скажите мне что-то, что не работает с моим кодом.
Cocco
9
В вашем коде нет ничего плохого с технической точки зрения. Тем не менее, присвоение имен переменным a, b, c, d и т. Д. И создание цепочек while затрудняет чтение кода. Таким образом, код не может научить чему-либо.
Ривер-Клер Уильямсон
3

Использование «include» для проверки, если элемент уже существует.

var arr = [1, 1, 4, 5, 5], darr = [], duplicates = [];

for(var i = 0; i < arr.length; i++){
  if(darr.includes(arr[i]) && !duplicates.includes(arr[i]))
    duplicates.push(arr[i])
  else
    darr.push(arr[i]);
}

console.log(duplicates);
<h3>Array with duplicates</h3>
<p>[1, 1, 4, 5, 5]</p>
<h3>Array with distinct elements</h3>
<p>[1, 4, 5]</p>
<h3>duplicate values are</h3>
<p>[1, 5]</p>

Srichakradhar
источник
Код возвращает отдельные элементы, но не приводит к данному результату. Пожалуйста, предоставьте полный правильный код.
RWC
3

ES6 предлагает структуру данных Set, которая в основном представляет собой массив, который не принимает дубликаты. С помощью структуры данных Set очень легко найти дубликаты в массиве (используя только один цикл).

Вот мой код

function findDuplicate(arr) {
var set = new Set();
var duplicates = new Set();
  for (let i = 0; i< arr.length; i++) {
     var size = set.size;
     set.add(arr[i]);
     if (set.size === size) {
         duplicates.add(arr[i]);
     }
  }
 return duplicates;
}
Roysh
источник
3

Я только что выяснил простой способ добиться этого с помощью фильтра массива

    var list = [9, 9, 111, 2, 3, 4, 4, 5, 7];
    
    // Filter 1: to find all duplicates elements
    var duplicates = list.filter(function(value,index,self) {
       return self.indexOf(value) !== self.lastIndexOf(value) && self.indexOf(value) === index;
    });
    
    console.log(duplicates);

alaahd
источник
3

Следующая логика будет проще и быстрее

// @Param:data:Array that is the source 
// @Return : Array that have the duplicate entries
findDuplicates(data: Array<any>): Array<any> {
        return Array.from(new Set(data)).filter((value) => data.indexOf(value) !== data.lastIndexOf(value));
      }

Преимущества:

  1. Одна строка :-P
  2. Вся встроенная структура данных помогает повысить эффективность
  3. Быстрее

Описание логики:

  1. Преобразование в набор для удаления всех дубликатов
  2. Итерация по заданным значениям
  3. При каждой проверке заданного значения в исходном массиве на условие «первый индекс значений не равен последнему индексу» ==> Затем выводится как дубликат, иначе он «уникален»

Примечание: методы map () и filter () эффективны и быстрее.

PranavKAndro
источник
1
Проверено это ... очень быстро. и это имеет смысл .. Жаль, что я думал об этом
Майкл