Отримати в масиві всі не унікальні значення (тобто: дублікат / декілька випадків)


418

Мені потрібно перевірити масив JavaScript, щоб побачити, чи є дублікати значень. Який найпростіший спосіб це зробити? Мені просто потрібно знайти, що таке дублювані значення - мені фактично не потрібні їх індекси або скільки разів вони дублюються.

Я знаю, що можу провести цикл через масив і перевірити всі інші значення на відповідність, але, схоже, має бути простіший спосіб.

Подібне запитання:


22
Здається, існують роки плутанини щодо того, що задає це питання. Мені потрібно було знати, які елементи в масиві дублюються: "Мені просто потрібно знайти, що таке дублювані значення". Правильна відповідь НЕ повинна видаляти дублікати з масиву. Це зворотне те, що я хотів: список дублікатів, а не список унікальних елементів.
Скотт Сондерс

Відповіді:


301

Ви можете сортувати масив, а потім пропустити його, а потім побачити, чи наступний (або попередній) індекс такий, як поточний. Якщо припустимо, що алгоритм сортування хороший, він повинен бути меншим, ніж 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


10
"Якщо припустимо, що алгоритм сортування хороший, це має бути менше O ^ 2". Зокрема, це може бути O (n * log (n)).
ESRogs

83
Цей сценарій працює не так добре з більш ніж двома дублікатами (наприклад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 : //dreaminginja JavaScript.wordpress.com/2008/08/22/elimining-duplicates/


18
Це хороший код, але, на жаль, він не робить те, про що я прошу.
Скотт Сондерс

67
Код вище (який мій - це мій блог) зближує вас. Маленький твіст і ти там. Перш за все, ви можете побачити, чи arr.length та out.length однакові. Якщо вони однакові, дублюваних елементів немає. Але ти хочеш ще трохи. Якщо ви хочете "зловити" дупи, як вони трапляються, перевірте, чи збільшується довжина масиву після рядка obj [arr [i]] = 0. Ніфт, так? :-) Дякую за приємні слова, Рафаель Монтанаро.
Носредна

6
@MarcoDemaio: Ага, ні, чому б код не працював з пробілами? Ви можете помістити все, що вам подобається, у назві властивості - просто не можна використовувати синтаксис крапок для доступу до одиниць із пробілами (а також реквізитів з різними іншими символами, які б порушили розбір).
Gijs

4
@Gijs: +1 ви праві. Я цього не знав. Але це все ще не працює, коли це масив об’єктів.
Марко Демайо

3
Цей алгоритм також має побічний ефект повернення відсортованого масиву, який може бути не тим, що потрібно.
асиметричний

165

Це моя відповідь із дублюючої нитки (!):

При написанні цього запису 2014 - усі приклади були для-циклів або 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

Знайдіть дублікати значень у масиві

Це має бути одним із найкоротших способів дійсно знайти дублікати значень у масиві. Як спеціально вимагає ОП, це копії не видаляє, а їх знаходить .

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 () (або, щоб бути зрозумілішим: суворий оператор порівняння ) підтримує.

Через зменшення () та indexOf () йому потрібно щонайменше IE 9.


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

30

Ви можете додати цю функцію або налаштувати її та додати її до прототипу масиву Javascript:

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

Це найкраще рішення, але будьте обережні, додаючи його до прототипу масиву, оскільки це зіпсує IE, якщо перегляне значення.
Сампса Суонінен

@RoyTinker perl теж їх підтримує, але я не мав ідеї, що 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 Array, які не реалізовані в IE <9.
Tim Down

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
Джеремі Piednoel

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
Josh

@TheDIMMReaper для другого 'a'масиву, всередині фільтра функціонує 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.


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


+1, оскільки це, безумовно, більш читабельний код за допомогою Array.indexOf, але, на жаль, це здається повільніше, ніж використання простого вкладеного циклу. Навіть у веб-переглядачах, які реалізують Array.indexOf наївно, як FF. Plz, подивіться на ці тести, які я зробив тут: jsperf.com/array-unique2, і повідомте мені ваші думки.
Марко Демайо

@shekhardesigner - відповідь оновлена. "r" - це масив, в якому ви шукаєте,
vsync

@vsync Мені довелося ініціалізувати, var r = [];щоб ваш код працював. І працював як шарм.
Шехар К. Шарма

@shekhardesigner - Вибачте за суміш, для рішення прототипу Array вам не потрібна 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]

1
Це дозволить повідомити, що один випадок undefinedє дублікатом.
Dem Pilafian

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

або при додаванні до прототипу ланцюга Array

//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, не повернула б їх.
mflodin

Крім того, я припускаю, що i&&це уникнути виходу за межі масиву, але це також означає, що перший елемент у відсортованому масиві не буде включений. У вашому прикладі немає 1в отриманому масиві. Тобто return i&&v!==o[i-1]?v:0;має бутиreturn v!==o[i-1];
mflodin

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Масив містить всі дублікати; він також може містити більше одного і того ж значення (наприклад, наш відфільтрований масив тут [ 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 код var i = коди .length; var дублікат = []; while (i--) {if (коди .indexOf (коди [i])! = i) {if (duplicate.indexOf (коди [i]) === -1) {duplicate.push (arr [i]) ; } code.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 () було б набагато простіше
tocqueville

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 Hehe, це означає indx !== ...- сувора нерівність.
Дарія

додавання лише для масиву об’єктівresult.filter((ele,indx) => indx !== result.map(e => e.name).indexOf(ele.name));
x-

4

Ця відповідь також може бути корисною, вона використовує js reduce operator / method для видалення дублікатів з масиву.

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])щоб видалити дублікати
kimbaudi

3

Наступна функція (варіант вже усунутої функції elimDuplicates), здається, виконує трюк, повертаючи 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;
}

3

Тільки для ES5 (тобто для поліпшення 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] );
    });

Мені подобається це просте рішення. Якщо ви хочете дублікати, вам потрібно спершу знайти ці дублікати, а потім зробити список дублікатів унікальним. [0, 4, 5, 5, 5, 2, 1, 3, 1, 1, 2, 1, 3] .sort (). Filter (функція (мені, i, arr) {return (i! == 0 ) && (me == arr [i-1]);}). filter (функція (мені, i, arr) {return (i === 0) || (мені! == 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 разів швидше, ніж більшість функцій тут. & 78x швидше в сафарі

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

EDIT Як зазначено в коментарях, ця функція повертає масив з унікальними елементами, проте питання вимагає знайти дублікати. у такому випадку проста модифікація цієї функції дозволяє висунути дублікати в масив, після чого за допомогою попередньої функції 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 ... вони Є багато відповідей, якщо шукати просте рішення. Якщо ви дійсно хочете дізнатися щось, я радий пояснити букву коду за буквою. Оскільки я не бачу реального питання у вашому коментарі, я думаю, ви просто шукаєте мотив, щоб спростувати мою відповідь .... продовжуйте ... у мене немає проблем з цим. Задайте справжнє запитання або скажіть мені щось, що не працює з моїм кодом.
кокко

9
З вашим кодом технічно немає нічого поганого. Зазначене, іменування змінних a, b, c, d тощо та ланцюжок під час циклів робить код важким для читання. Отже, код не вчить нічого.
Рівер Вільямсон

3

Використання "включає" для перевірки, чи елемент вже існує.

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>


Код видає чіткі елементи, але не призводить до даного результату. Введіть повний правильний код.
RWC

3

ES6 пропонує встановити структуру даних, яка в основному є масивом, який не приймає дублікатів. За допомогою структури даних "Набір даних" існує дуже простий спосіб знайти дублікати в масиві (використовуючи лише один цикл).

Ось мій код

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

3

Я щойно придумав простий спосіб досягти цього за допомогою фільтра Array

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


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 () ефективні та швидші.


1
Випробував це ... дуже швидко. і це має сенс .. бажаю, щоб я подумав про це
Майкл Рема
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.