Подтвердить что ты не робот

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

У меня есть этот код:

var ar = [10,7,8,3,4,7,6];

function isin(n,a){
  for (var i=0;i<a.length;i++){
    if (a[i]== n) {
      var b = true;
      return b;
    } else {
      var c = false;
      return c;
   }
  }
}

function unique(a){
  var arr = [];
  for (var i=0;i<a.length;i++){
    if (!isin(a[i],arr)){
      arr.push(a[i]);
    }
  }

 return arr;
}

alert(unique(ar));

В этом коде я пытаюсь создать новый уникальный массив (без дубликатов) из исходного. Но я все еще получаю исходный массив! Где моя ошибка?

4b9b3361

Ответ 1

Использование простого массива и возврат ключей ассоциативного массива (содержащий только "уникальные" значения из заданного массива) более эффективно:

function ArrNoDupe(a) {
    var temp = {};
    for (var i = 0; i < a.length; i++)
        temp[a[i]] = true;
    var r = [];
    for (var k in temp)
        r.push(k);
    return r;
}

$(document).ready(function() {
    var arr = [10, 7, 8, 3, 4, 3, 7, 6];
    var noDupes = ArrNoDupe(arr);
    $("#before").html("Before: " + arr.join(", "));
    $("#after").html("After: " + noDupes.join(", "));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="before"></div>
<div id="after"></div>

Ответ 2

Или для тех, кто ищет однострочный (простой и функциональный):

var a = ["1", "1", "2", "3", "3", "1"];
var unique = a.filter(function(item, i, ar){ return ar.indexOf(item) === i; });

Ответ 3

Изменить: обратите внимание на предупреждение Daniel. Учитывая это и то, что говорят официальные документы (см. Ниже), возможно, использование этого не является отличной идеей!


Если вы используете jQuery, его unique() функция делает следующее:

var ar = [1, 2, 1, 2, 2, 3];    
ar = $.unique(ar);
console.log(ar);  // [3, 2, 1] 

В документации написано:

Обратите внимание, что это работает только с массивами элементов DOM, а не строк или числа.

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

Ответ 4

Вы можете использовать новый родной new Set(list) объект в ES6/ES2015. (т.е. Babel, Typescript, или тех, кому повезло, что все целевые браузеры поддерживают ES2015).

// I never use this, because it an iterator, not an array
let s = new Set(list);

или, если вы хотите связать цепочку с помощниками массива, используйте новый оператор распространения ... в ES6/ES2015, чтобы разложить его в массив:

const unique = (list) => {
  return [...new Set(list)];
}

Вам нужен массив для цепных методов, таких как sort():

const convertText = (textToConvert) => {
  let list = unique(textToConvert.split(/\r?\n/g))
    .sort() // this will error if using uniqueAsIterator() version...
    .filter(x => x != "NULL");
  return list;
}

Ответ 5

В дополнение к использованию фильтра отвечает Джош Мак, вы можете сделать его сумасшедшим короче в es6 с помощью утилиты функции стрелки;

const a = ["1", "1", "2", "3", "3", "1"];
let unique = a.filter((it, i, ar) => ar.indexOf(it) === i);
// unique = [1, 2, 3]

Ответ 6

Поскольку ваш метод isin возвращает true или false после проверки первого элемента.

измените его на это:

function isin(n,a){
  for (var i=0;i<a.length;i++){
    if (a[i]== n){
    return true;

    }
  }
  return false;
}

Ответ 7

Вы должны использовать indexOf вместо своей функции isIn:

function unique(a){
  var arr = [];
  for (var i=0;i<a.length;i++){
    if ( arr.indexOf(a[i]) == -1){
        arr.push(a[i]);
    }
}

Ответ 8

Где моя ошибка??

Прямо здесь:

... else {
      var c = false;
      return c;
   }

Это приводит к тому, что функция isin имеет значение false, если n не соответствует первому элементу массива. Тело цикла всегда возвращает значение перед переходом к следующему элементу.

Извлеките else-предложение и переместите return false в нижнюю часть метода:

function isin(n,a){
    for (var i=0;i<a.length;i++) {
        if (a[i] == n)
            return true;

    return false;
}

Обратите внимание, что метод isin может быть сразу заменен (или даже заменен) на вызов indexOf.

Ответ 9

То, как я это делал, это использовать массив "назад", поэтому, когда я нажимаю на него, я использую ключ вместо значения, например:

var arr = [];
$('input[type=checkbox]', SearchResults).each( function() {
    if( $(this).is(':checked') )
        arr[ $(this).data('client_id') ] = true;
}

Затем я смотрю на клавиши, а не на значения.

Ответ 10

И с некоторым удовольствием ES5...

function uniqueArray(array) {
    var temp = array.reduce(function(previous, current) {
        previous[current] = true;
        return previous;
    }, {});

    return Object.keys(temp);
}

Ответ 11

Я знаю, что немного опоздал, чтобы ответить на этот вопрос. Но ни один из ответов не имеет того, что я сделал бы. Мне нравится использовать сращивание для такого рода вещей. Здесь действительно простой script, который будет делать именно то, что вам нужно:

function unique(originalArray){
    var ar = originalArray.slice(0);//Make a copy of the array and store it in ar
    var i = ar.length;
    while(i--){  //Iterate through the array
        if(ar.indexOf(ar[i],i+1)>-1){  //If the array has a duplicate
            ar.splice(i,1);  //Remove that element!
        }
    }
    return ar; //Return the new, more unique array
}

Ответ 12

В соответствии с принятым ответом . Вот эквивалент CoffeeScript:

unique = (a) ->
  temp = {}
  for i in [0...a.length]
    temp[a[i]] = true
  r = []
  for k of temp
    r.push(k)
  return r

Ответ 13

Я сделал аналогичный поиск, я нашел этот ответ действительно хорошим:

Уникальные значения в массиве [duplicate]

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

Cheer.