jQuery를 사용하여 Javascript 객체의 두 배열 비교


93

두 배열의 JavaScript 개체가 동일한 지 비교하고 싶습니다. 객체는 각 배열에서 동일한 순서가 아닐 수 있습니다. 각 배열에는 10 개 이상의 개체가 있어서는 안됩니다. 나는 jQuery가이 문제에 대한 우아한 해결책을 가지고 있다고 생각했지만 온라인에서 많은 것을 찾을 수 없었다.

무차별 중첩 $.each(array, function(){})솔루션이 작동 할 수 있다는 것을 알고 있지만 내가 알지 못하는 내장 기능이 있습니까?

감사.

답변:


277

쉬운 방법이 있습니다 ...

$(arr1).not(arr2).length === 0 && $(arr2).not(arr1).length === 0

위의 결과가 true를 반환하면 요소의 순서가 다른 경우에도 두 배열이 동일합니다.

참고 : 이것은 JSON 객체를 사용할 때 <3.0.0 jquery 버전에서만 작동합니다.


12
+1, 그러나 동일한 속성을 포함하는 객체와 배열을 비교할 때 true와 같습니다. f.ex[0,1] == {0:0,1:1,length=2}
David Hellsing

4
$(arr1).not(arr2).length == 0충분하지 않습니까?
Alexxus 2014 년

10
@Alexxus, not는 같음 함수가 아니라 필터 함수 이기 때문에 두 비교가 모두 필요 합니다. 그것을 시도 [1,2]하고 [1]. 하나 위해서는, 당신은 얻을 것이다 [], 또 다른, 당신은 얻을 것이다 [2].
Noyo

3
배열에 중복이있는 경우 true를 반환합니다. 따라서`[1,1,2,2,3,3] == [1,2,3]`은 참입니다.
Philll_t

3
not3.0.0-rc1부터 jQuery 는 더 이상 일반 객체에서 작동하지 않습니다. 참조 github.com/jquery/jquery/issues/3147
마크 - 앙드레 Lafortune

35

나는 또한 오늘 이것을 찾고 있었고 다음을 발견했습니다. http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256BFB0077DFFD

고려 된 몇 가지 성능 고려 사항을 언급하지만 이것이 좋은 솔루션인지 여부는 알 수 없습니다.

나는 jQuery 도우미 메서드의 아이디어를 좋아합니다. @David 차라리 비교 방법이 다음과 같이 작동하는 것을보고 싶습니다.

jQuery.compare(a, b)

나는 내가하는 일을 이해하지 못한다.

$(a).compare(b)

여기서 a와 b는 배열입니다. 일반적으로 $ (something) 때 DOM 요소 작업을 위해 선택기 문자열을 전달합니다.

또한 정렬 된 배열의 정렬 및 '캐싱'과 관련하여 :

  • 루프를 통해 매번 '캐싱'이 아니라 메서드 시작 부분에서 한 번 정렬한다고 생각하지 않습니다. 이 정렬은 compare (b)를 호출 할 때마다 계속 발생합니다. 그것은 단지 의미 론적이지만 ...
  • for (var i = 0; t [i]; i ++) { ...이 루프는 t 배열의 어딘가에 거짓 값이 포함되어 있으면 일찍 완료 되므로 $ ([1, 2, 3, 4]). compare ( [1, false, 2, 3]) true 반환 !
  • 더 중요한 어레이 정렬 () 메소드 어레이 정렬 장소를 이렇게, = t.sort () b를 VAR을 가 정렬 원래 어레이의 정렬 된 복사본을 생성하지 않는다 ... 원래 배열하고 또한 할당 기준 에을 그것에 B . 나는 비교 방법이 부작용을 가져야한다고 생각하지 않는다.

우리가해야 할 일은 배열을 작업하기 전에 복사하는 것 같습니다. jQuery 방식으로 수행하는 방법에 대해 찾을 수있는 가장 좋은 답변은 바로 여기에있는 John Resig입니다! 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]

2
실제로 나는이 방법을 '비교'라기보다는 '배열 비교'라고 명명 할 것입니다. 그게 작동하도록 설계된 유일한 방법이기 때문입니다.
Anentropic

실제로 스팟. 감사합니다.
dimitarvp

14

내 접근 방식은 상당히 달랐습니다. 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');
}

주의 : 그의 방법은 두 컬렉션이 비슷한 방식으로 정렬되어 있다고 가정합니다. 그렇지 않으면 잘못된 결과를 제공합니다!


1
두 배열에 대해 동일한 순서를 보장하면서 단위 테스트에서 배열을 비교하는 간단한 방법이 필요했습니다. 아주 좋아요, 감사합니다.
aymericbeaumet 2014

내 하루를 구 해주셔서 감사합니다
Sourabh Kumar Sharma

12

두 배열을 문자열로 변환하고 비교

if (JSON.stringify(array1) == JSON.stringify(array2))
{
    // your code here
}

1
중첩 배열을 비교하고 순서가 중요한 경우에 좋습니다.
Pierre de LESPINAY 2014-06-26

3

배열과 객체를 자세히 비교할 방법이 필요했기 때문에이 토론을 찾았습니다. 여기에있는 예제를 사용하여 다음을 생각해 냈습니다 (명확성을 위해 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

3

제 경우에는 비교 배열에 숫자문자열 만 포함됩니다 . 이 솔루션은 저에게 효과적이었습니다.

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

1

이 작업을 수행하는 좋은 "jQuery"방법이 없다고 생각하지만 효율성이 필요한 경우 특정 키 (고유 개체 필드 중 하나)로 배열 중 하나를 매핑 한 다음 다른 배열을 반복하여 비교를 수행합니다. 방금 빌드 한지도 또는 연관 배열과 비교합니다.

효율성이 문제가되지 않는다면 A의 모든 객체를 B의 모든 객체와 비교하십시오. | A | 및 | B | 작 으면 괜찮을 것입니다.


@Stefan, 빠른 응답에 감사드립니다. 매핑 아이디어에 대한 예제 코드를 게시 할 수 있습니까? 감사.
MegaMatt 2009

1

음, 배열의 내용 만 비교하고 싶다면 유용한 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

좋은 해결책이지만 이것이 동일한 요소를 가지고 있지만 순서가 다른 배열을 설명하고 있는지 확실하지 않습니다.
MegaMatt 2009

(! equal) false를 반환하면 이동할 수 있습니다. 함수가 다시 실행되지 않도록 $ .each의 맨 아래로 내려가십시오. 그리고 동등하게 반환 할 수 있습니다. 비교를 피하기 위해.
Matt

1

배열을 문자열로 변경하고 비교

var arr = [1,2,3], 
arr2 = [1,2,3]; 
console.log(arr.toString() === arr2.toString());

1

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;
  }
});

0

나는 또한 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';
  }
}

0

[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()}

여기에 연주 할 바이올린이 있습니다 .


0

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>


-3

이 시도

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;
}

이는 a와 b를 모두 수정하고 첫 번째 요소 만 비교합니다. wtf.
ScottJ

1
@ScottJ Mr.AH 문제는 두 배열을 비교하는 것입니다. 두 배열이 같으면 정렬 한 후 a [0] == b [0]. 뭐야.
예외

2
AH가 무엇을 의미하는지 모르겠지만 Google은 도움이되지 않았습니다. 하지만 내 의견이 너무 근거가 없다면 왜이 코드가 2 월 21 일에 완전히 다시 작성 되었습니까?
ScottJ

@ScottJ 아마 AH === wtf
예외
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.