Як перевірити, чи має масив повторювані значення в Javascript?


95

Можливий дублікат:
найпростіший спосіб знайти повторювані значення в масиві javascript

Як перевірити, чи має масив повторювані значення?

Якщо деякі елементи в масиві однакові, поверніть true. В іншому випадку поверніть false.

['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist

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



2
Не хочу видаляти список дублікатів. Я просто хочу знати true або false, якщо в списку є дублікати.
user847495

7
Це питання не є дублікатом. Оскільки @ user847495 просто хоче перевірити, чи існують дублікати, рішення швидше / простіше, ніж те, що потрібно для пошуку всіх випадків дублікатів. Наприклад, ви можете зробити це: codr.io/v/bvzxhqm
alden

2
за допомогою підкреслення , проста технікаvar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Сай Рам

4
Не дублікат позначеного питання. Будь ласка, зверніть увагу, перш ніж позначати запитання як такі.
Джон Вайс

Відповіді:


223

Якщо у вас є середовище ES2015 (на момент написання статті: io.js, IE11, Chrome, Firefox, WebKit щоночі), то наступне буде працювати і буде швидким (а саме O (n)):

function hasDuplicates(array) {
    return (new Set(array)).size !== array.length;
}

Якщо вам потрібні лише рядкові значення в масиві, буде працювати наступне:

function hasDuplicates(array) {
    var valuesSoFar = Object.create(null);
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (value in valuesSoFar) {
            return true;
        }
        valuesSoFar[value] = true;
    }
    return false;
}

Ми використовуємо "хеш-таблицю" valuesSoFar, ключі якої є значеннями, які ми бачили в масиві до цього часу. Ми робимо пошук за допомогою, inщоб побачити, чи вже було помічено це значення; якщо так, ми виходимо з циклу і повертаємося true.


Якщо вам потрібна функція, яка працює не лише з рядковими значеннями, наступне буде працювати, але не настільки ефективно; це O (n 2 ) замість O (n).

function hasDuplicates(array) {
    var valuesSoFar = [];
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (valuesSoFar.indexOf(value) !== -1) {
            return true;
        }
        valuesSoFar.push(value);
    }
    return false;
}

Різниця полягає лише в тому, що ми використовуємо масив замість хеш-таблиці для valuesSoFar, оскільки "хеш-таблиці" JavaScript (тобто об'єкти) мають лише рядкові ключі. Це означає, що ми втрачаємо час пошуку O (1) in, замість цього отримуємо час пошуку O (n) indexOf.


3
Про перший приклад, який ви дали. Хіба перевірка не зовсім інша? Якщо ваша функція названа hasDuplicates, тоді вона повинна перевірити, чи насправді не зменшився розмір набору під час кастингу, так? Тому логічний оператор повинен бути, !==а не===
Tim Daubenschütz

PLS редагувати. Я не можу редагувати, оскільки не змінюю більше 6 символів.
Тім Даубеншютц

1
Згідно з MDN IE11 не підтримує конструктор, використаний у першому прикладі
adam77

Звичайна версія JS повертається trueдля наступного масиву:[1, '1']
Kunal

Таким чином, "якщо вам потрібні лише рядкові значення в масиві", що передують відповіді.
Доменік

4

Іншим підходом (також для елементів об’єкта / масиву в масиві 1 ) може бути 2 :

function chkDuplicates(arr,justCheck){
  var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
  arrtmp.sort();
  while(len--){
   var val = arrtmp[len];
   if (/nul|nan|infini/i.test(String(val))){
     val = String(val);
    }
    if (tmp[JSON.stringify(val)]){
       if (justCheck) {return true;}
       dupes.push(val);
    }
    tmp[JSON.stringify(val)] = true;
  }
  return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true);                           //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true);                //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true);          //=> false
chkDuplicates([1,2,3,4,5,1,2]);                            //=> [1,2]
chkDuplicates([1,2,3,4,5]);                                //=> null

Дивіться також...

1 потрібен браузер, який підтримує JSON, або бібліотека JSON, якщо ні.
2 edit: функцію тепер можна використовувати для простої перевірки або повернення масиву повторюваних значень


3
Проблеми, не пов’язані з showstopper, про які варто пам’ятати: 1) змінює оригінальний масив, що підлягає сортуванню; 2) не розрізняє null, NaN, Infinity, +Infinity, і -Infinity; 3) об’єкти вважаються рівними, якщо вони мають однакові власні властивості, навіть якщо вони мають різні прототипи.
Доменік

1
@Domenic: так, мав би про це згадати. Відредаговано, щоб обійти мутацію вихідного масиву.
KooiInc

@Domenic: виправлено на null / NaN / [+/-] Нескінченність, див. Редагування.
KooiInc

@Domenic: Випуск 3) насправді не є проблемою для мене, оскільки це саме те, що я хочу. Мене не хвилює прототип, а лише значення.
благоговіння

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