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
4 Answers
Reset to default 2It'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 forisSorted
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
}