Поиск вложенных дубликатов массивов в JavaScript. (Вложенный массив uniq в lodash/подчеркивание)

Я пытаюсь определить, содержит ли массив массивов JavaScript дубликаты. Это возможно? Я сначала пытаюсь увидеть, могу ли я удалить дубликаты, а затем выполнить проверку равенства, но я не могу пройти мимо первой части. Вот что возвращает символ подчеркивания:

var arr1 = [[1,2], [2,3], [1,2]];
var arr2 = _.uniq(arr1);

var arraysAreEqual = _.isEqual(arr1, arr2);

console.log(arraysAreEqual, arr1, arr2);
// true

Jsbin: http://jsbin.com/vogumo/1/edit?js,console

Кто-нибудь знает, как определить, содержит ли массив повторяющиеся массивы?

Ответ 1

Это немного неряшливо, но (возможно)

var arr2 = _.uniq(arr1, function(item) {
    return JSON.stringify(item);
});

даст вам правильный результат

Ответ 2

Из документация underscore.js:

uniq _.uniq(array, [isSorted], [iteratee]) Псевдоним: уникальный
Производит бездискретная версия массива, с использованием === для тестирования объекта равенство. Если вы заранее знаете, что массив отсортирован, true для isSorted будет работать гораздо быстрее алгоритм. Если ты хочешь вычислять уникальные элементы на основе преобразования, передавать итерацию Функция.

Но массивы нельзя строго сравнивать в JavaScript.

Следовательно, вы можете использовать функцию преобразования для сравнения с uniq. Например:

console.log([1,2] === [1,2]) // false, can't strict compare arrays
console.log([1,2].toString()) // "1,2" - string representation
console.log([1,2].toString() === [1,2].toString()) // true, strings can be compared

var valueToString = function(v) {return v.toString()}; // transform array to string
var arr1 = [[1,2], [2,3], [1,2]];
var arr2 = _.uniq(arr1, false, valueToString); // compare based on transformation
var arraysAreEqual = _.isEqual(arr1, arr2);

console.log("arraysAreEqual:", arraysAreEqual, arr1, arr2); 
// false
// [[1, 2], [2, 3], [1, 2]]
// [[1, 2], [2, 3]]

Примечание, что преобразование в строку является "взломанным": вам было бы лучше сравнивать каждое значение массива, как обсуждалось в fooobar.com/questions/14175/....

Используя предлагаемую реализацию equals в этом вопросе, вам нужно будет реализовать свою собственную версию uniq, которая использует equals вместо ===.

реализация uniq в Underscore очень проста - он создает новый массив result и проходит через данный массив. Если текущее значение еще не получено, вставьте его.

console.log("Using array comparison:");
arrayEquals = function (array1, array2) {
    // if any array is a falsy value, return
    if (!array1 || !array2)
        return false;

    // compare lengths - can save a lot of time 
    if (array1.length != array2.length)
        return false;

    for (var i = 0, l=array1.length; i < l; i++) {
        // Check if we have nested arrays
        if (array1[i] instanceof Array && array2[i] instanceof Array) {
            // recurse into the nested arrays
            if (!arrayEquals(array1[i],array2[i]))
                return false;       
        }           
        else if (array1[i] !== array2[i]) { 
            return false;   
        }        
    }       
    return true;
};

_.uniqArrays = function(array) {
  if (array == null) return [];
  var result = [];
  for (var i = 0, length = array.length; i < length; i++) {
    var value = array[i];
    var arrayEqualsToValue = arrayEquals.bind(this, value); // arrayEquals with first argument set to value
    var existing = _.find(result, arrayEqualsToValue); // did we already find this?
    if (!existing) {
      result.push(value);
    }
  }
  return result;
};

var arr3 = _.uniqArrays(arr1);
arraysAreEqual = _.isEqual(arr1, arr3);
console.log("arraysAreEqual:", arraysAreEqual, arr1, arr3); // false

Я сделал jsbin со всем кодом, если вы хотите поиграть.

Ответ 3

В последнем lodash (4.6.1) вы можете сделать что-то вроде этого:

if (_.uniqWith(arr, _.isEqual).length < arr.length) {
  // then there were duplicates
}

Ответ 4

Попробуйте следующее:

var numArray = [1, 7, 3, 0, 9, 7, 8, 6, 2, 3];
var duplicates = [];
var sortednumArray = numArray.sort();


for (var i = 0; i < sortednumArray.length; i++) {
    //console.log(sortednumArray[i]);
    if (sortednumArray[i] == sortednumArray[i + 1]) {
        duplicates.push(sortednumArray[i]);
    }
}

if (duplicates.length == 0) {
    console.log("Soted Array:");
    for(var i = 0; i < sortednumArray.length; i++) {
        console.log(sortednumArray[i]);
    }
} else {
    console.log("Duplicates:");
    for(var i = 0; i < duplicates.length; i++){
        console.log(duplicates[i]);
    }
}

Программа выталкивает все дубликаты в массив с именем "duplicates", а затем отображает его, но если ни один не присутствует, он отображает отсортированную версию numArray