如何比较 javascript 数组的内容,而不是它们的顺序?
How to compare contents of javascript array, but not the order of them?
正如标题所说,我想比较两个js数组,我只关心内容是否相同,但我不关心它们的顺序是否相同。所以我期望的是:
[1, 2, 3, 3] == [1, 2, 3, 3] // True
[1, 2, 3, 3] == [1, 3, 2, 3] // True
[1, 2, 3, 3] == [1, 2] // False
[1, 2, 3, 3] == [1, 2, 3] // False
[1, 2, 3, 3] == [1, 2, 3, 3, 3] // False
[1, 2, 3, 3] == [1, "2, 3, 3"] // False
显然比较运算符不起作用。从 this SO answer 我得到了下面的 Array.prototype 方法,但不幸的是,它也会检查顺序是否相同。
所以有人知道我如何检查两个 js 数组是否包含相同的元素,而不考虑元素的顺序吗?欢迎所有提示!
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
在比较之前对它们进行排序:
从下面的评论中,如果你想让 2 个 arr 包含不同的原语 type.add 这个排序函数。
function s(x,y){
var pre = ['string' , 'number' , 'bool']
if(typeof x!== typeof y )return pre.indexOf(typeof y) - pre.indexOf(typeof x);
if(x === y)return 0;
else return (x > y)?1:-1;
}
var arr1 = [1, 2, 3, 3].sort(s);
var arr2 = [1, 3, 2, 3].sort(s);
arr1.equals(arr2);// true
这是一个适用于原始值的解决方案。它使用对象作为原始映射并计算每个值的出现次数。但是,它还考虑了每个值的数据类型。
它首先检查数组的长度,作为快捷方式:
function equals(a, b) {
if (a.length !== b.length) {
return false;
}
var seen = {};
a.forEach(function(v) {
var key = (typeof v) + v;
if (!seen[key]) {
seen[key] = 0;
}
seen[key] += 1;
});
return b.every(function(v) {
var key = (typeof v) + v;
if (seen[key]) {
seen[key] -= 1;
return true;
}
// not (anymore) in the map? Wrong count, we can stop here
});
}
正如标题所说,我想比较两个js数组,我只关心内容是否相同,但我不关心它们的顺序是否相同。所以我期望的是:
[1, 2, 3, 3] == [1, 2, 3, 3] // True
[1, 2, 3, 3] == [1, 3, 2, 3] // True
[1, 2, 3, 3] == [1, 2] // False
[1, 2, 3, 3] == [1, 2, 3] // False
[1, 2, 3, 3] == [1, 2, 3, 3, 3] // False
[1, 2, 3, 3] == [1, "2, 3, 3"] // False
显然比较运算符不起作用。从 this SO answer 我得到了下面的 Array.prototype 方法,但不幸的是,它也会检查顺序是否相同。
所以有人知道我如何检查两个 js 数组是否包含相同的元素,而不考虑元素的顺序吗?欢迎所有提示!
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
在比较之前对它们进行排序:
从下面的评论中,如果你想让 2 个 arr 包含不同的原语 type.add 这个排序函数。
function s(x,y){
var pre = ['string' , 'number' , 'bool']
if(typeof x!== typeof y )return pre.indexOf(typeof y) - pre.indexOf(typeof x);
if(x === y)return 0;
else return (x > y)?1:-1;
}
var arr1 = [1, 2, 3, 3].sort(s);
var arr2 = [1, 3, 2, 3].sort(s);
arr1.equals(arr2);// true
这是一个适用于原始值的解决方案。它使用对象作为原始映射并计算每个值的出现次数。但是,它还考虑了每个值的数据类型。
它首先检查数组的长度,作为快捷方式:
function equals(a, b) {
if (a.length !== b.length) {
return false;
}
var seen = {};
a.forEach(function(v) {
var key = (typeof v) + v;
if (!seen[key]) {
seen[key] = 0;
}
seen[key] += 1;
});
return b.every(function(v) {
var key = (typeof v) + v;
if (seen[key]) {
seen[key] -= 1;
return true;
}
// not (anymore) in the map? Wrong count, we can stop here
});
}