Używanie jQuery do porównywania dwóch tablic obiektów Javascript
Mam dwie tablice obiektów JavaScript, które chciałbym porównać, aby sprawdzić, czy są takie same. Obiekty nie mogą (i najprawdopodobniej nie będą) znajdować się w tej samej kolejności w każdej tablicy. Każda tablica nie powinna zawierać więcej niż 10 obiektów. Myślałem, że jQuery może mieć eleganckie rozwiązanie tego problemu, ale nie byłem w stanie znaleźć wiele w Internecie.
Wiem, że zagnieżdżone $.each(array, function(){})
rozwiązanie brute może działać, ale czy jest jakaś wbudowana funkcja, której nie jestem świadom?
14 answers
Jest prosty sposób...
$(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0
Jeśli powyższe zwraca true, obie tablice są takie same, nawet jeśli elementy są w innej kolejności.
Uwaga: to działa tylko dla wersji jquery
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-29 21:14:57
Ja też dziś tego szukałem i znalazłem: http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD
Nie wiem, czy to dobre rozwiązanie, chociaż wspominają o pewnych aspektach wydajności wziętych pod uwagę.
Podoba mi się pomysł metody pomocniczej jQuery. @Dawid wolałbym zobaczyć Twoją metodę porównywania do pracy jak:
jQuery.compare(a, b)
Nie ma dla mnie sensu robić:
$(a).compare(b)
Gdzie a i b są tablicami. Zwykle, gdy $(something) przekazywałbyś łańcuch selektora do pracy z elementami DOM.
Również w odniesieniu do sortowania i "buforowania" posortowanych tablic:
- Nie sądzę, aby sortowanie raz na początku metody zamiast za każdym razem przez pętlę było "buforowaniem". Sortowanie będzie miało miejsce za każdym razem, gdy wywołasz compare (b). To tylko semantyka, ale...
- for (var i = 0; t [I]; i++) { ...pętla kończy się wcześnie, jeśli tablica T zawiera false wartość w niej gdzieś, więc $([1, 2, 3, 4]).compare([1, false, 2, 3]) zwraca true !
- co ważniejsze metoda array sort () sortuje tablicę w miejsce, więc robi to var b = T.sort()...nie tworzy posortowanej kopii oryginalnej tablicy, sortuje tablicę oryginalną, a także przypisuje referencję do niej w b. Nie sądzę, żeby metoda porównywania miała skutki uboczne.
It seems what we need to do jest skopiowanie tablic przed rozpoczęciem pracy nad nimi. Najlepszą odpowiedzią, jaką mogłem znaleźć na to, jak to zrobić w jQuery, był nikt inny niż John Resig tutaj NA SO! jaki jest najbardziej efektywny sposób na głębokie sklonowanie obiektu w JavaScript? (Zobacz komentarze do jego odpowiedzi dla tablicy wersji receptury klonowania obiektów)
W takim przypadku myślę, że kod będzie:
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]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:19
Moje podejście było zupełnie inne - spłaszczyłem obie kolekcje używając JSON.stringify i użył zwykłego ciągu porównującego, aby sprawdzić równość.
Tzn.
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: proszę zauważyć, że jego metoda zakłada, że obie kolekcje są sortowane w podobny sposób, jeśli nie, to daje fałszywy wynik!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-30 14:27:48
Konwertuj obie tablice na ciąg znaków i porównaj
if (JSON.stringify(array1) == JSON.stringify(array2))
{
// your code here
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-05 22:26:17
Znalazłem tę dyskusję, ponieważ potrzebowałem sposobu głębokiego porównywania tablic i obiektów. Korzystając z przykładów tutaj, wymyśliłem następujące (podzielone na 3 metody dla jasności):
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;
}
});
Testowanie
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-10 17:03:56
W moim przypadku porównywane tablice zawierają tylko liczby i ciągi . To rozwiązanie zadziałało dla mnie:
function are_arrs_equal(arr1, arr2){
return arr1.sort().toString() === arr2.sort().toString()
}
Przetestujmy to!
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 07:58:19
Myślę, że nie ma na to dobrego sposobu "jQuery" , ale jeśli potrzebujesz wydajności, odwzoruj jedną z tablic według określonego klucza (jedno z unikalnych pól obiektu), a następnie wykonaj porównanie przez zapętlenie drugiej tablicy i porównanie z mapą lub tablicą asocjacyjną, którą właśnie zbudowałeś.
Jeśli wydajność nie jest problemem, po prostu porównaj każdy obiekt w A Z Każdym obiektem w B. dopóki |A |i / B / są małe, powinno być dobrze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-20 20:35:28
Cóż, jeśli chcesz porównać tylko zawartość tablic, jest przydatna funkcja 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-20 21:06:16
Zmień tablicę na string i porównaj
var arr = [1,2,3],
arr2 = [1,2,3];
console.log(arr.toString() === arr2.toString());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-13 16:38:46
Nice one liner z Sudhakar R jako jQuery global method.
/**
* 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;
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:15
Znalazłem to również, gdy szukałem porównania tablic z jQuery. W moim przypadku miałem ciągi, które wiedziałem, że są tablicami:
var needle = 'apple orange';
var haystack = 'kiwi orange banana apple plum';
Ale zależało mi, czy to jest pełne dopasowanie, czy tylko częściowe, więc użyłem czegoś takiego, opartego na odpowiedzi Sudhakara 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';
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 00:47:12
Jeśli duplikaty mają znaczenie takie, że [1, 1, 2]
nie powinny być równe [2, 1]
, ale powinny być równe [1, 2, 1]
, Oto rozwiązanie zliczające odniesienia:
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()}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-04 00:27:28
var arr1 = [
{name: 'a', Val: 1},
{name: 'b', Val: 2},
{name: 'c', Val: 3}
];
var arr2 = [
{name: 'c', Val: 3},
{name: 'x', Val: 4},
{name: 'y', Val: 5},
{name: 'z', Val: 6}
];
var _isEqual = _.intersectionWith(arr1, arr2, _.isEqual);// common in both array
var _difference1 = _.differenceWith(arr1, arr2, _.isEqual);//difference from array1
var _difference2 = _.differenceWith(arr2, arr1, _.isEqual);//difference from array2
console.log(_isEqual);// common in both array
console.log(_difference1);//difference from array1
console.log(_difference2);//difference from array2
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-10 10:52:10
Spróbuj tego
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-21 05:08:03