最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

underscore.js - Finding nested duplicate arrays in JavaScript. (Nested Array uniq in lodashunderscore) - Stack Overflow

programmeradmin0浏览0评论

I am trying to determine if an array of JavaScript arrays contains duplicates. Is this possible? I am first trying to see if I can strip the duplicates out and then do an equality check but I cannot get past the first part. Here is what underscore returns:

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

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

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

Jsbin: ,console

Anyone know of a way to determine if the array contains duplicate arrays?

I am trying to determine if an array of JavaScript arrays contains duplicates. Is this possible? I am first trying to see if I can strip the duplicates out and then do an equality check but I cannot get past the first part. Here is what underscore returns:

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./vogumo/1/edit?js,console

Anyone know of a way to determine if the array contains duplicate arrays?

Share Improve this question asked Jan 9, 2015 at 1:09 Scotty BollingerScotty Bollinger 2,3734 gold badges20 silver badges25 bronze badges 1
  • When you say 'duplicate', do you mean the arrays are the same object, or that the arrays have the same length and order of items, or have the same length but not order of items? – Xotic750 Commented Jan 9, 2015 at 1:19
Add a ment  | 

4 Answers 4

Reset to default 2

It's a little sloppy, but (possible)

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

will give you a correct result

Try This:

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

Program pushes all duplicates to an array called 'duplicates' then displays it, but if none are present, it displays the sorted version of numArray

From the underscore.js documentation:

uniq _.uniq(array, [isSorted], [iteratee]) Alias: unique
Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to pute unique items based on a transformation, pass an iteratee function.

But arrays can't be strictly pared in JavaScript.

Therefore, you can use a transformation function to enable parison with uniq. For example:

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

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); // pare 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]]

Note that transforming to string is "hacky": you would be better off paring each value of the array, as discussed in this StackOverflow question.

By using the proposed equals implementation in that question, you would need to implement your own version of uniq that uses equals instead of ===.

The implementation of uniq in Underscore is very straight-forward - it creates a new result array and loops through the given array. If the current value is not already in result, insert it.

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

    // pare 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

I made a jsbin with all the code, if you want to play around.

In the latest lodash (4.6.1) you could do something like this:

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

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论