如何使用JavaScript检查两个数组是否相等?
如何检查这些数组是否相等,并获得一个如果相等则返回如何使用JavaScript检查两个数组是否相等?,javascript,Javascript,如何检查这些数组是否相等,并获得一个如果相等则返回true的方法 jQuery是否为此提供了任何方法?根据Tim James和Fox32的评论,下面应该检查空值,假设两个空值不相等 var a = [1, 2, 3]; var b = [3, 2, 1]; var c = new Array(1, 2, 3); alert(a == b + "|" + b == c); 函数数组等于(a,b){return!!a&&!!b&&!(a数组等于([1,2,3],[1,2,3]) 符合事实的 >数
true
的方法
jQuery是否为此提供了任何方法?根据Tim James和Fox32的评论,下面应该检查空值,假设两个空值不相等
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
alert(a == b + "|" + b == c);
函数数组等于(a,b){return!!a&&!!b&&!(a数组等于([1,2,3],[1,2,3])
符合事实的
>数组_等于([1,3,4],[1,2,3])
错误的
>数组_等于(空[1,2,3])
错误的
>数组_等于(null,null)
错误的
[2021 changelog:option4的错误修复:在js对象上(即使不包括NaN!=NaN
和'5'==5
('5'==5
,'2'),即使这看起来非常简单,有时它也非常有用。如果您只需要查看两个数组是否具有相同的项并且它们的顺序相同,请尝试以下操作:
function arraysEqual(a1,a2) {
/* WARNING: arrays must not contain {objects} or behavior may be undefined */
return JSON.stringify(a1)==JSON.stringify(a2);
}
但是,这不适用于模式高级情况,例如:
[1, 2, 3].toString() == [1, 2, 3].toString()
true
[1, 2, 3,].toString() == [1, 2, 3].toString()
true
[1,2,3].toString() == [1, 2, 3].toString()
true
这取决于你需要什么。这种方法很糟糕,但我把它放在这里作为参考,所以其他人避免使用这种方法:
使用@ninjagecko的选项1对我来说最有效:
[[1,2],[3]].toString() == [[1],[2,3]].toString()
true
它还将处理null和未定义的情况,因为我们正在将它添加到数组的原型中,并检查另一个参数是否也是数组。jQuery有这样的方法
自制的通用严格相等检查可以如下所示:
Array.prototype.equals = function(array) {
return array instanceof Array && JSON.stringify(this) === JSON.stringify(array) ;
}
a = [1, [2, 3]]
a.equals([[1, 2], 3]) // false
a.equals([1, [2, 3]]) // true
测试:
function deepEquals(obj1, obj2, parents1, parents2) {
"use strict";
var i;
// compare null and undefined
if (obj1 === undefined || obj2 === undefined ||
obj1 === null || obj2 === null) {
return obj1 === obj2;
}
// compare primitives
if (typeof (obj1) !== 'object' || typeof (obj2) !== 'object') {
return obj1.valueOf() === obj2.valueOf();
}
// if objects are of different types or lengths they can't be equal
if (obj1.constructor !== obj2.constructor || (obj1.length !== undefined && obj1.length !== obj2.length)) {
return false;
}
// iterate the objects
for (i in obj1) {
// build the parents list for object on the left (obj1)
if (parents1 === undefined) parents1 = [];
if (obj1.constructor === Object) parents1.push(obj1);
// build the parents list for object on the right (obj2)
if (parents2 === undefined) parents2 = [];
if (obj2.constructor === Object) parents2.push(obj2);
// walk through object properties
if (obj1.propertyIsEnumerable(i)) {
if (obj2.propertyIsEnumerable(i)) {
// if object at i was met while going down here
// it's a self reference
if ((obj1[i].constructor === Object && parents1.indexOf(obj1[i]) >= 0) || (obj2[i].constructor === Object && parents2.indexOf(obj2[i]) >= 0)) {
if (obj1[i] !== obj2[i]) {
return false;
}
continue;
}
// it's not a self reference so we are here
if (!deepEquals(obj1[i], obj2[i], parents1, parents2)) {
return false;
}
} else {
// obj2[i] does not exist
return false;
}
}
}
return true;
};
对于数字和字符串等基本值,这是一个简单的解决方案:
// message is displayed on failure
// clean console === all tests passed
function assertTrue(cond, msg) {
if (!cond) {
console.log(msg);
}
}
var a = 'sdf',
b = 'sdf';
assertTrue(deepEquals(b, a), 'Strings are equal.');
b = 'dfs';
assertTrue(!deepEquals(b, a), 'Strings are not equal.');
a = 9;
b = 9;
assertTrue(deepEquals(b, a), 'Numbers are equal.');
b = 3;
assertTrue(!deepEquals(b, a), 'Numbers are not equal.');
a = false;
b = false;
assertTrue(deepEquals(b, a), 'Booleans are equal.');
b = true;
assertTrue(!deepEquals(b, a), 'Booleans are not equal.');
a = null;
assertTrue(!deepEquals(b, a), 'Boolean is not equal to null.');
a = function () {
return true;
};
assertTrue(deepEquals(
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
],
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
]), 'Arrays are equal.');
assertTrue(!deepEquals(
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': 1.0
},
true]
],
[
[1, 1, 1],
[2, 'asdf', [1, a]],
[3, {
'a': '1'
},
true]
]), 'Arrays are not equal.');
a = {
prop: 'val'
};
a.self = a;
b = {
prop: 'val'
};
b.self = a;
assertTrue(deepEquals(b, a), 'Immediate self referencing objects are equal.');
a.prop = 'shmal';
assertTrue(!deepEquals(b, a), 'Immediate self referencing objects are not equal.');
a = {
prop: 'val',
inside: {}
};
a.inside.self = a;
b = {
prop: 'val',
inside: {}
};
b.inside.self = a;
assertTrue(deepEquals(b, a), 'Deep self referencing objects are equal.');
b.inside.self = b;
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equeal. Not the same instance.');
b.inside.self = {foo: 'bar'};
assertTrue(!deepEquals(b, a), 'Deep self referencing objects are not equal. Completely different object.');
a = {};
b = {};
a.self = a;
b.self = {};
assertTrue(!deepEquals(b, a), 'Empty object and self reference of an empty object.');
调用sort()
将确保元素的顺序无关紧要。调用toString()
将创建一个值以逗号分隔的字符串,以便可以测试两个字符串是否相等。jQuery没有比较数组的方法。但是确实有这样一个方法:,并且它还可以处理各种其他情况(如对象文字)。要继续使用提供的示例:
a = [1,2,3]
b = [3,2,1]
a.sort().toString() == b.sort().toString()
顺便说一下:下划线还有很多jQuery缺少的其他方法,所以它是jQuery的一个很好的补充
编辑:正如评论中指出的那样,现在只有当两个数组的元素顺序相同时,上述方法才有效,即:
var a=[1,2,3];
var b=[3,2,1];
var c=new Array(1,2,3);
alert(_.isEqual(a, b) + "|" + _.isEqual(b, c));
幸运的是,Javascript有一个内置的方法来解决这个问题,sort
:
_.isEqual([1,2,3], [1,2,3]); // true
_.isEqual([1,2,3], [3,2,1]); // false
这是您应该做的。请不要使用stringify
或
_.isEqual([1,2,3].sort(), [3,2,1].sort()); // true
函数数组相等(a,b){
如果(a==b)返回true;
如果(a==null | | b==null)返回false;
如果(a.length!==b.length)返回false;
//如果您不关心内部元素的顺序
//数组,您应该在这里对两个数组进行排序。
//请注意,对数组调用sort将修改该数组。
//您可能需要先克隆阵列。
对于(变量i=0;i
使用JavaScript 1.6版,操作非常简单:
function arraysEqual(a, b) {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;
// If you don't care about the order of the elements inside
// the array, you should sort both arrays here.
// Please note that calling sort on an array will modify that array.
// you might want to clone your array first.
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
例如,[].equals([])
给出true
,而[1,2,3].equals([1,3,2])
产生false
这不是一个简单的方法。我也需要它,但想要一个可以接受任意两个变量并测试相等性的函数。它包括非对象值、对象、数组和任何级别的嵌套
在您的问题中,您提到希望忽略数组中值的顺序。我的解决方案本质上不会这样做,但您可以通过在比较相等性之前对数组进行排序来实现
我还想要将非对象强制转换为字符串的选项,以便[1,2]=[“1”,2]
因为我的项目使用了下划线,所以我决定将其作为一个mixin函数,而不是一个独立函数
你可以在电脑上测试
这是我的mxin:
Array.prototype.equals = function( array ) {
return this.length == array.length &&
this.every( function(this_i,i) { return this_i == array[i] } )
}
这是您使用它的方式:
_.mixin({
/**
Tests for the equality of two variables
valA: first variable
valB: second variable
stringifyStatics: cast non-objects to string so that "1"===1
**/
equal:function(valA,valB,stringifyStatics){
stringifyStatics=!!stringifyStatics;
//check for same type
if(typeof(valA)!==typeof(valB)){
if((_.isObject(valA) || _.isObject(valB))){
return false;
}
}
//test non-objects for equality
if(!_.isObject(valA)){
if(stringifyStatics){
var valAs=''+valA;
var valBs=''+valB;
ret=(''+valA)===(''+valB);
}else{
ret=valA===valB;
}
return ret;
}
//test for length
if(_.size(valA)!=_.size(valB)){
return false;
}
//test for arrays first
var isArr=_.isArray(valA);
//test whether both are array or both object
if(isArr!==_.isArray(valB)){
return false;
}
var ret=true;
if(isArr){
//do test for arrays
_.each(valA,function(val,idx,lst){
if(!ret){return;}
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}else{
//do test for objects
_.each(valA,function(val,idx,lst){
if(!ret){return;}
//test for object member exists
if(!_.has(valB,idx)){
ret=false;
return;
}
// test for member equality
ret=ret && _.equal(val,valB[idx],stringifyStatics);
});
}
return ret;
}
});
要演示嵌套,可以执行以下操作:
_.equal([1,2,3],[1,2,"3"],true)
它处理所有可能的内容,甚至在对象的结构中引用自身
_.equal(
['a',{b:'b',c:[{'someId':1},2]},[1,2,3]],
['a',{b:'b',c:[{'someId':"1"},2]},["1",'2',3]]
,true);
使用map()
和reduce()
:
如果希望检查对象数组是否相等,则顺序无关紧要,即
areEqual([{id:“0”},{id:“1”}],{id:“1”},{id:“0”}])///true
您需要首先对数组进行排序。通过组合sortBy
和isEqual
,您拥有所需的所有工具:
function arraysEqual (a1, a2) {
return a1 === a2 || (
a1 !== null && a2 !== null &&
a1.length === a2.length &&
a1
.map(function (val, idx) { return val === a2[idx]; })
.reduce(function (prev, cur) { return prev && cur; }, true)
);
}
编辑:由于sortBy
返回一个新数组,因此在排序之前无需克隆数组。原始数组不会发生变化
请注意,对于lodash的isEqual
,顺序确实很重要。如果未首先对每个数组应用sortBy
,则上面的示例将返回false
。如果使用lodash并且不想修改任何一个数组,则可以使用。它将两个数组作为集合进行比较,并返回包含它们的集合r差。如果该差的长度为零,则两个数组基本相等:
// arr1 & arr2: Arrays of objects
// sortProperty: the property of the object with which you want to sort
// Note: ensure every object in both arrays has your chosen sortProperty
// For example, arr1 = [{id: "v-test_id0"}, {id: "v-test_id1"}]
// and arr2 = [{id: "v-test_id1"}, {id: "v-test_id0"}]
// sortProperty should be 'id'
function areEqual (arr1, arr2, sortProperty) {
return _.areEqual(_.sortBy(arr1, sortProperty), _.sortBy(arr2, sortProperty))
}
检查数组大小后,通过for循环检查每个值
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
_.xor(a, b).length === 0
true
_.xor(b, c).length === 0
true
函数等式(a,b){
如果(a.length==b.length){
对于(变量i=0;i
既然Javascript中的null==null
(甚至更多,null==null
),那么在数组等价性检查中将两个null也视为相等不是更合适吗?正如中指出的,数组相等([1[2,3]],[1,2],3])
将返回true
。另外,数组相等([1,2],[1,2]”)
被视为相等,数组也被视为相等([],[“”])
+1,一点注释:对于allTrue
,您还可以使用array.each
和返回数组元素值的函数。JSON.stringify(null)=='null'
(
function arraysEqual (a1, a2) {
return a1 === a2 || (
a1 !== null && a2 !== null &&
a1.length === a2.length &&
a1
.map(function (val, idx) { return val === a2[idx]; })
.reduce(function (prev, cur) { return prev && cur; }, true)
);
}
// arr1 & arr2: Arrays of objects
// sortProperty: the property of the object with which you want to sort
// Note: ensure every object in both arrays has your chosen sortProperty
// For example, arr1 = [{id: "v-test_id0"}, {id: "v-test_id1"}]
// and arr2 = [{id: "v-test_id1"}, {id: "v-test_id0"}]
// sortProperty should be 'id'
function areEqual (arr1, arr2, sortProperty) {
return _.areEqual(_.sortBy(arr1, sortProperty), _.sortBy(arr2, sortProperty))
}
var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);
_.xor(a, b).length === 0
true
_.xor(b, c).length === 0
true
function equalArray(a, b) {
if (a.length === b.length) {
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
} else {
return false;
}
}