使用jQuery来比较两个Javascript对象数组
我有两个JavaScript对象数组,我想比较它们是否相同。 对象可能不(也可能不会)在每个数组中的顺序相同。 每个数组不应超过10个对象。 我认为jQuery可能有一个优雅的解决这个问题,但我无法find很多在线。
我知道一个暴力嵌套的$.each(array, function(){})
解决scheme可以工作,但有没有内置函数,我不知道?
谢谢。
有一个简单的方法…
$(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0
如果上述返回true,则即使元素的顺序不同,两个数组也是相同的。
注意:这只适用于jquery版本<3.0.0
我今天也在找这个,发现: http : //www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD
不知道这是否是一个好的解决scheme,虽然他们提到了一些性能考虑因素。
我喜欢jQuery帮助器方法的想法。 @大卫我宁愿看到你的比较方法工作如:
jQuery.compare(a, b)
我没有理由去做:
$(a).compare(b)
其中a和b是数组。 通常当你$(something)时,你会传递一个select器string来处理DOM元素。
另外关于sorting和“caching”sorting的数组:
- 我不认为在方法开始时进行一次sorting,而不是每次循环都是“caching”。 每当你打电话比较(b)时,sorting仍然会发生。 这只是语义,但…
- for(var i = 0; t [i]; i ++){ …如果你的t数组在某个地方包含一个假的值,这个循环会提前结束,所以$([1,2,3,4])。 [1,false,2,3])返回true !
- 更重要的是,数组sort()方法对数组进行sorting,所以var b = t.sort() …不会创build原始数组的sorting副本,它会对原始数组进行sorting,并将引用它在b 。 我不认为比较方法应该有副作用。
看来我们需要做的是在对它们进行处理之前复制数组。 我可以find最好的答案,如何以jQuery的方式做到这一点是在这里约翰Resig莫属! 什么是在JavaScript中深入克隆对象的最有效方法? (请参阅关于对象克隆配方的arrays版本的回答的评论)
在这种情况下,我认为它的代码是:
jQuery.extend({ compare: function (arrayA, arrayB) { if (arrayA.length != arrayB.length) { return false; } // sort modifies original array // (which are passed by reference to our method!) // so clone the arrays before sorting var a = jQuery.extend(true, [], arrayA); var b = jQuery.extend(true, [], arrayB); a.sort(); b.sort(); for (var i = 0, l = a.length; i < l; i++) { if (a[i] !== b[i]) { return false; } } return true; } }); var a = [1, 2, 3]; var b = [2, 3, 4]; var c = [3, 4, 2]; jQuery.compare(a, b); // false jQuery.compare(b, c); // true // c is still unsorted [3, 4, 2]
我的方法是完全不同的 – 我使用JSON.stringify展开了两个集合,并使用普通的string比较来检查相等性。
即
var arr1 = [ {Col: 'a', Val: 1}, {Col: 'b', Val: 2}, {Col: 'c', Val: 3} ]; var arr2 = [ {Col: 'x', Val: 24}, {Col: 'y', Val: 25}, {Col: 'z', Val: 26} ]; if(JSON.stringify(arr1) == JSON.stringify(arr2)){ alert('Collections are equal'); }else{ alert('Collections are not equal'); }
注意:请注意,他的方法假设两个集合都以类似的方式sorting,如果不是,它会给你一个错误的结果!
将两个数组转换为string并进行比较
if (JSON.stringify(array1) == JSON.stringify(array2)) { // your code here }
我发现这个讨论,因为我需要一种方法来深入比较数组和对象。 用这里的例子,我想出了以下内容(为了清晰起见,分成了三种方法):
jQuery.extend({ compare : function (a,b) { var obj_str = '[object Object]', arr_str = '[object Array]', a_type = Object.prototype.toString.apply(a), b_type = Object.prototype.toString.apply(b); if ( a_type !== b_type) { return false; } else if (a_type === obj_str) { return $.compareObject(a,b); } else if (a_type === arr_str) { return $.compareArray(a,b); } return (a === b); } }); jQuery.extend({ compareArray: function (arrayA, arrayB) { var a,b,i,a_type,b_type; // References to each other? if (arrayA === arrayB) { return true;} if (arrayA.length != arrayB.length) { return false; } // sort modifies original array // (which are passed by reference to our method!) // so clone the arrays before sorting a = jQuery.extend(true, [], arrayA); b = jQuery.extend(true, [], arrayB); a.sort(); b.sort(); for (i = 0, l = a.length; i < l; i+=1) { a_type = Object.prototype.toString.apply(a[i]); b_type = Object.prototype.toString.apply(b[i]); if (a_type !== b_type) { return false; } if ($.compare(a[i],b[i]) === false) { return false; } } return true; } }); jQuery.extend({ compareObject : function(objA,objB) { var i,a_type,b_type; // Compare if they are references to each other if (objA === objB) { return true;} if (Object.keys(objA).length !== Object.keys(objB).length) { return false;} for (i in objA) { if (objA.hasOwnProperty(i)) { if (typeof objB[i] === 'undefined') { return false; } else { a_type = Object.prototype.toString.apply(objA[i]); b_type = Object.prototype.toString.apply(objB[i]); if (a_type !== b_type) { return false; } } } if ($.compare(objA[i],objB[i]) === false){ return false; } } return true; } });
testing
var a={a : {a : 1, b: 2}}, b={a : {a : 1, b: 2}}, c={a : {a : 1, b: 3}}, d=[1,2,3], e=[2,1,3]; console.debug('a and b = ' + $.compare(a,b)); // a and b = true console.debug('b and b = ' + $.compare(b,b)); // b and b = true console.debug('b and c = ' + $.compare(b,c)); // b and c = false console.debug('c and d = ' + $.compare(c,d)); // c and d = false console.debug('d and e = ' + $.compare(d,e)); // d and e = true
在我的例子中,比较数组只包含数字和string 。 这个解决scheme为我工作:
function are_arrs_equal(arr1, arr2){ return arr1.sort().toString() === arr2.sort().toString() }
我们来testing一下吧!
arr1 = [1, 2, 3, 'nik'] arr2 = ['nik', 3, 1, 2] arr3 = [1, 2, 5] console.log (are_arrs_equal(arr1, arr2)) //true console.log (are_arrs_equal(arr1, arr3)) //false
我不认为有一个好的“jQuery”方法来做到这一点,但如果你需要效率,通过一个特定的键(唯一的对象字段之一)映射其中一个数组,然后通过循环其他数组并与刚刚构build的地图或关联数组进行比较。
如果效率不是问题,只需将A中的每个对象与B中的每个对象进行比较。只要| A | 和| B | 很小,你应该没问题。
那么,如果你只想比较数组的内容,有一个有用的jQuery函数$ .inArray()
var arr = [11, "String #1", 14, "String #2"]; var arr_true = ["String #1", 14, "String #2", 11]; // contents are the same as arr var arr_false = ["String #1", 14, "String #2", 16]; // contents differ function test(arr_1, arr_2) { var equal = arr_1.length == arr_2.length; // if array sizes mismatches, then we assume, that they are not equal if (equal) { $.each(arr_1, function (foo, val) { if (!equal) return false; if ($.inArray(val, arr_2) == -1) { equal = false; } else { equal = true; } }); } return equal; } alert('Array contents are the same? ' + test(arr, arr_true)); //- returns true alert('Array contents are the same? ' + test(arr, arr_false)); //- returns false
将数组改为string并进行比较
var arr = [1,2,3], arr2 = [1,2,3]; console.log(arr.toString() === arr2.toString());
从Sudhakar R作为jQuery全局方法的不错的一行。
/** * Compare two arrays if they are equal even if they have different order. * * @link https://stackoverflow.com/a/7726509 */ jQuery.extend({ /** * @param {array} a * First array to compare. * @param {array} b * Second array to compare. * @return {boolean} * True if both arrays are equal, otherwise false. */ arrayCompare: function (a, b) { return $(a).not(b).get().length === 0 && $(b).not(a).get().length === 0; } });
我也发现这一点,当与jQuery做一些数组比较。 在我的情况下,我有string,我知道是arrays:
var needle = 'apple orange'; var haystack = 'kiwi orange banana apple plum';
但是我关心的是,如果这是一场完全的比赛还是只是部分的比赛,所以我用了Sudhakar R的回答:
function compareStrings( needle, haystack ){ var needleArr = needle.split(" "), haystackArr = haystack.split(" "), compare = $(haystackArr).not(needleArr).get().length; if( compare == 0 ){ return 'all'; } else if ( compare == haystackArr.length ) { return 'none'; } else { return 'partial'; } }
如果重复事项使得[1, 1, 2]
不应该等于[2, 1]
而应该等于[1, 2, 1]
,那么这里是一个参考计数的解决scheme:
const arrayContentsEqual = (arrayA, arrayB) => { if (arrayA.length !== arrayB.length) { return false} const refCount = (function() { const refCountMap = {}; const refCountFn = (elt, count) => { refCountMap[elt] = (refCountMap[elt] || 0) + count} refCountFn.isZero = () => { for (let elt in refCountMap) { if (refCountMap[elt] !== 0) { return false}} return true} return refCountFn})() arrayB.map(eltB => refCount(eltB, 1)); arrayA.map(eltA => refCount(eltA, -1)); return refCount.isZero()}
这里是小提琴玩 。
尝试这个
function check(c,d){ var a = c, b = d,flg = 0; if(a.length == b.length) { for(var i=0;i<a.length;i++) a[i] != b[i] ? flg++ : 0; } else { flg = 1; } return flg = 0; }