В Javascript, как я могу проверить, если массив имеет повторяющиеся значения?

Возможный дубликат:
Самый простой способ найти повторяющиеся значения в массиве JavaScript

Как проверить, есть ли в массиве повторяющиеся значения?

Если некоторые элементы в массиве совпадают, вернуть true. В противном случае верните false.

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

12 ответов

Решение

Если у вас есть среда ES2015 (на момент написания статьи: io.js, IE11, Chrome, Firefox, WebKit nightly), то будет работать следующее и будет быстро (а именно 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 (n2) вместо 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,

Вы можете использовать SET для удаления дубликатов и сравнения. Если вы скопируете массив в набор, он удалит все дубликаты. Затем просто сравните длину массива с размером набора.

      function hasDuplicates(a) {

  const noDups = new Set(a);

  if (a.length !== noDups.size) {
    return true;
  } else {
    return false;
  }
}

Однолинейные решения с ES6

Другой подход (также для элементов объекта / массива в массиве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: функция теперь может использоваться для простой проверки или для возврата массива повторяющихся значений.

Если вы имеете дело с простыми значениями, вы можете использовать array.some() а также indexOf()

например, скажем vals является ["b", "a", "a", "c"]

      const allUnique = !vals.some((v, i) => vals.indexOf(v) < i);

some()вернет истину, если какое-либо выражение вернет истину. Здесь мы перебираем значения (из индекса 0) и вызываем indexOf(), который вернет индекс первого вхождения данного элемента (или -1, если не в массиве). Если его идентификатор меньше текущего, перед ним должно быть хотя бы одно такое же значение. таким образом, итерация 3 вернет истину, поскольку "a" (с индексом 2) сначала будет найдено по индексу 1.

Вы можете воспользоваться indexOf а также lastIndexOf. если оба индекса не совпадают, у вас есть дубликат.

      function containsDuplicates(a) {
  for (let i = 0; i < a.length; i++) {
    if (a.indexOf(a[i]) !== a.lastIndexOf(a[i])) {
      return true
    }
  }
  return false
}

просто, вы можете использовать Array.prototype.everyфункция

      function isUnique(arr) {
  const isAllUniqueItems = input.every((value, index, arr) => {
    return arr.indexOf(value) === index; //check if any duplicate value is in other index
  });

  return isAllUniqueItems;
}

Зачем использовать этот метод:

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

Объяснение:

В этом примере массив повторяется, элемент такой же, как array[i] i — это позиция массива, в котором в данный момент находится цикл, затем функция проверяет позицию в читаемом массиве, который инициализируется как пустой, если элемент не находится в массиве чтения, он вернет -1 и будет помещен в массив чтения, в противном случае он вернет свою позицию и не будет отправлен, как только весь элемент массива будет повторен, массив чтения будет быть напечатано на консоли

Одна приятная вещь о решениях, которые используют Setявляется O(1)производительность при поиске существующих элементов в списке, вместо того, чтобы зацикливаться на нем.

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

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

Согласно JSBench.me , должно быть достаточно хорошо для различных вариантов использования. Подход с заданным размером является самым быстрым без дубликатов, а проверка некоторых + indexOf является самой неудачной с очень ранним дублированием, но это решение хорошо работает в обоих сценариях, что делает его хорошей универсальной реализацией.

          this.selectedExam = [];
    // example exam obj: {examId:1, name:'ExamName'}
    onExamSelect(exam: any) {
    if(!this.selectedExam.includes(exam?.name)){ 
      this.selectedExam.push(exam?.name);
    }}

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

      function hasAllUniqueChars( s ){ 
    for(let c=0; c<s.length; c++){
        for(let d=c+1; d<s.length; d++){
            if((s[c]==s[d])){
                return false;
            }
        }
    }
    return true;
}

Ну, я немного искал в интернете для вас, и я нашел эту удобную ссылку.

Самый простой способ найти повторяющиеся значения в массиве JavaScript

Вы можете адаптировать пример кода, который приведен в приведенной выше ссылке, любезно предоставленного "swilliams", к вашему решению.

Другие вопросы по тегам