У меня есть два массива JavaScript-объектов, которые я бы хотел сравнить, чтобы убедиться, что они одинаковые. Объекты не могут (и, скорее всего, не будут) находиться в одном порядке в каждом массиве. Каждый массив должен иметь не более 10 объектов. Я думал, что у jQuery может быть элегантное решение этой проблемы, но я не смог найти много онлайн.
Я знаю, что может работать грубое вложенное решение $.each(array, function(){})
, но есть ли встроенная функция, о которой я не знаю?
Спасибо.
Ответ 1
Существует простой способ...
$(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0
Если приведенное выше значение возвращает true, оба массива одинаковы, даже если элементы находятся в другом порядке.
ПРИМЕЧАНИЕ. Это работает только для jQuery-версий < 3.0.0
Ответ 2
Я тоже искал это сегодня и нашел:
http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD
Не знаю, хорошо ли это решение, хотя они упоминают некоторые соображения производительности, принятые во внимание.
Мне нравится идея вспомогательного метода jQuery.
@David Я бы предпочел, чтобы ваш метод сравнения работал следующим образом:
jQuery.compare(a, b)
Мне не имеет смысла делать это:
$(a).compare(b)
где a и b - массивы. Обычно, когда вы $(что-то), вы должны передать селекторную строку для работы с элементами DOM.
Также относительно сортировки и "кэширования" отсортированных массивов:
- Я не думаю, что сортировка один раз в начале метода, а не каждый раз через цикл - это кеширование. Сорт все равно будет происходить каждый раз, когда вы вызываете сравнение (b). Это просто семантика, но...
- for (var я = 0; t [i]; я ++) {... этот цикл заканчивается раньше, если массив t содержит в нем ложное значение, поэтому $([1, 2, 3, 4]). Compare ([1, false, 2, 3]) возвращает true!
- Что еще более важно, метод sort() массива сортирует массив на месте, поэтому var b = t.sort()... не создает отсортированную копию исходного массива, это сортирует исходный массив, а также присваивает ссылку на него в b. Я не думаю, что метод сравнения должен иметь побочные эффекты.
Кажется, что нам нужно сделать, это скопировать массивы, прежде чем работать над ними. Лучший ответ, который я мог найти, как это сделать в jQuery, был не кто иной, как Джон Ресиг здесь, на SO! Каков наиболее эффективный способ глубокого клонирования объекта в JavaScript? (см. комментарии к его ответу для версии массива рецепта клонирования объектов)
В этом случае я думаю, что для этого кода будет:
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]
Ответ 3
Мой подход был совсем другим - я сгладил обе коллекции, используя JSON.stringify, и использовал обычную строку, сравнив проверку равенства.
т.е.
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');
}
NB: Обратите внимание, что его метод предполагает, что обе коллекции сортируются аналогичным образом, а если нет, это даст вам ложный результат!
Ответ 4
Преобразуйте оба массива в строку и сравните
if (JSON.stringify(array1) == JSON.stringify(array2))
{
// your code here
}
Ответ 5
Я нашел это обсуждение, потому что мне нужен способ глубокого сравнения массивов и объектов. Используя примеры здесь, я придумал следующее (разбитое на 3 метода для ясности):
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;
}
});
Тестирование
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
Ответ 6
В моем случае сравниваемые массивы содержат только числа и строки. Это решение работало для меня:
function are_arrs_equal(arr1, arr2){
return arr1.sort().toString() === arr2.sort().toString()
}
Протестируйте его!
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
Ответ 7
Я не думаю, что есть хороший способ "jQuery", но если вам нужна эффективность, сопоставьте один из массивов с помощью определенного ключа (одно из уникальных полей объекта), а затем выполните сравнение путем циклирования другой массив и сравнение с картой или ассоциативным массивом, который вы только что создали.
Если эффективность не является проблемой, просто сравните каждый объект в с каждым объектом в B. До тех пор, пока | A | и | B | малы, вы должны быть в порядке.
Ответ 8
Ну, если вы хотите сравнить только содержимое массивов, есть полезная функция 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
Ответ 9
Хороший один вкладыш из 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;
}
});
Ответ 10
Измените массив на строку и сравните
var arr = [1,2,3],
arr2 = [1,2,3];
console.log(arr.toString() === arr2.toString());
Ответ 11
Я также нашел это, когда смотрел, чтобы сделать некоторые сравнения массивов с jQuery. В моем случае у меня были строки, которые я знал как массивы:
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';
}
}
Ответ 12
Если дубликаты имеют значение, так что [1, 1, 2]
не должно быть равно [2, 1]
, но должно быть равно [1, 2, 1]
, вот решение для подсчета ссылок:
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()}
Вот скрипка, чтобы играть с.
Ответ 13
Попробуйте это
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;
}