IT story

두 배열이 JavaScript와 같은지 확인하는 방법은 무엇입니까?

hot-time 2020. 4. 25. 09:55
반응형

두 배열이 JavaScript와 같은지 확인하는 방법은 무엇입니까? [복제]


이 질문에는 이미 답변이 있습니다.

var a = [1, 2, 3];
var b = [3, 2, 1];
var c = new Array(1, 2, 3);

alert(a == b + "|" + b == c);

데모

이 배열 true이 동일한 지 확인하고 동일한 경우 반환하는 메서드를 어떻게 얻을 수 있습니까?

jQuery는 이에 대한 방법을 제공합니까?


이것이 당신이해야 할 일입니다. stringifynor를 사용하지 마십시오 < >.

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

옵션 1

가장 쉬운 옵션은 null! ==를 제외하고 거의 모든 경우에 작동 undefined하지만 둘 다 JSON 표현으로 변환되어 null동일하게 간주됩니다.

function arraysEqual(a1,a2) {
    /* WARNING: arrays must not contain {objects} or behavior may be undefined */
    return JSON.stringify(a1)==JSON.stringify(a2);
}

( 배열에 객체가 포함되어 있으면 작동하지 않을 수 있습니다. 그래도 객체와 작동하는지 여부는 JSON 구현이 키를 정렬하는지 여부에 따라 다릅니다. 예를 들어 JSON의 JSON {1:2,3:4}이 같거나 같지 않을 수 있습니다.{3:4,1:2}; 이것은 구현에 따라 다르며 사양은 그 어떤 것도 보증하지 않습니다. [2017 업데이트 : 실제로 ES6 사양은 이제 객체 키가 1) 정수 속성, 2) 정의 된 순서대로 속성, 3) 정의 된 순서대로 기호 속성 순서로 반복되도록 보장합니다. 따라서 JSON.stringify 구현이 다음을 따르는 경우 === 의미에서 동일한 객체 (== 의미에서는 NOT)는 동일한 값으로 문자열 화됩니다. 더 많은 연구가 필요했습니다. 따라서 역순으로 속성을 가진 객체의 사악한 복제본을 만들 수 있다고 생각하지만 우연히 발생하는 것을 상상할 수는 없습니다 ...] 적어도 Chrome에서 JSON.stringify 함수는 정의 된 순서대로 키를 반환하는 경향이 있지만 (적어도 내가 알았지 만)이 동작은 언제든지 변경 될 수 있으므로 의존해서는 안됩니다. 목록에서 객체를 사용하지 않기로 선택하면 제대로 작동합니다. 목록에 모두 고유 한 ID를 가진 개체가있는 경우 할 수 있습니다 a1.map(function(x)}{return {id:x.uniqueId}}). 목록에 임의의 객체가 있으면 옵션 # 2를 읽을 수 있습니다.)

이것은 중첩 배열에서도 작동합니다.

그러나 이러한 문자열을 작성하고 가비지 수집하는 오버 헤드로 인해 약간 비효율적입니다.


옵션 2

특별한 경우를 처리하기 위해 재정의 할 수있는 "적절한"옵션 (예 : 일반 객체 및 null / 정의되지 않은 사용자 정의 객체 등)

// generally useful functions
function type(x) { // does not work in general, but works on JSONable objects we care about... modify as you see fit
    // e.g.  type(/asdf/g) --> "[object RegExp]"
    return Object.prototype.toString.call(x);
}
function zip(arrays) {
    // e.g. zip([[1,2,3],[4,5,6]]) --> [[1,4],[2,5],[3,6]]
    return arrays[0].map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });
}

 

// helper functions
function allCompareEqual(array) {
    // e.g.  allCompareEqual([2,2,2,2]) --> true
    // does not work with nested arrays or objects
    return array.every(function(x){return x==array[0]});
}

function isArray(x){ return type(x)==type([]) }
function getLength(x){ return x.length }
function allTrue(array){ return array.reduce(function(a,b){return a&&b},true) }
    // e.g. allTrue([true,true,true,true]) --> true
    // or just array.every(function(x){return x});

 

function allDeepEqual(things) {
    // works with nested arrays
    if( things.every(isArray) )
        return allCompareEqual(things.map(getLength))     // all arrays of same length
               && allTrue(zip(things).map(allDeepEqual)); // elements recursively equal

    //else if( this.every(isObject) )
    //  return {all have exactly same keys, and for 
    //          each key k, allDeepEqual([o1[k],o2[k],...])}
    //  e.g. ... && allTrue(objectZip(objects).map(allDeepEqual)) 

    //else if( ... )
    //  extend some more

    else
        return allCompareEqual(things);
}

데모:

allDeepEqual([ [], [], [] ])
true
allDeepEqual([ [1], [1], [1] ])
true
allDeepEqual([ [1,2], [1,2] ])
true
allDeepEqual([ [[1,2],[3]], [[1,2],[3]] ])
true

allDeepEqual([ [1,2,3], [1,2,3,4] ])
false
allDeepEqual([ [[1,2],[3]], [[1,2],[],3] ])
false
allDeepEqual([ [[1,2],[3]], [[1],[2,3]] ])
false
allDeepEqual([ [[1,2],3], [1,[2,3]] ])
false

이것을 일반 함수처럼 사용하려면 다음을 수행하십시오.

function allDeepEqual2() {
    return allDeepEqual([].slice.call(arguments));
}

데모:

allDeepEqual2([[1,2],3], [[1,2],3])
true

옵션 3

편집 : 그것은 2016 년이며 이전의 너무 복잡한 답변이 나를 괴롭 혔습니다. 이 재귀적이고 명령적인 "재귀 프로그래밍 101"구현은 코드를 실제로 단순하게 유지하며 가능한 가장 빠른 시점에서 실패합니다 (효율성 제공). 또한 불필요한 임시 데이터 구조를 생성하지 않습니다 (일반적으로 함수형 프로그래밍에는 문제가 없지만 여기서는 깨끗하게 유지하십시오).

이 배열을 비어 있지 않은 배열에 적용하려면 seriesOfArrays.reduce (arraysEqual)를 수행하면됩니다.

이 함수는 Object.defineProperties를 사용하여 Array.prototype에 연결하는 것과 달리 자체 정의 된 기능입니다. 정의되지 않은 값을 전달하면 키 오류가 발생하지 않습니다 (그러나 원하는 경우 훌륭한 디자인 결정) .

이것은 OP의 원래 질문에만 답변합니다.

function arraysEqual(a,b) {
    /*
        Array-aware equality checker:
        Returns whether arguments a and b are == to each other;
        however if they are equal-lengthed arrays, returns whether their 
        elements are pairwise == to each other recursively under this
        definition.
    */
    if (a instanceof Array && b instanceof Array) {
        if (a.length!=b.length)  // assert same length
            return false;
        for(var i=0; i<a.length; i++)  // assert each element equal
            if (!arraysEqual(a[i],b[i]))
                return false;
        return true;
    } else {
        return a==b;  // if not both arrays, should be the same
    }
}

예 :

arraysEqual([[1,2],3], [[1,2],3])
true
arraysEqual([1,2,3], [1,2,3,4])
false
arraysEqual([[1,2],[3]], [[1,2],[],3])
false
arraysEqual([[1,2],[3]], [[1],[2,3]])
false
arraysEqual([[1,2],3], undefined)
false
arraysEqual(undefined, undefined)
true
arraysEqual(1, 2)
false
arraysEqual(null, null)
true
arraysEqual(1, 1)
true
arraysEqual([], 1)
false
arraysEqual([], undefined)
false
arraysEqual([], [])
true

이것을 js Objects를 사용하여 JSON과 같은 데이터 구조에 적용하려면 그렇게 할 수 있습니다. 다행히도 모든 객체 키가 고유하다는 것을 보장하므로 OwnProperties 객체를 반복하여 키별로 정렬 한 다음 정렬 된 키 배열이 같고 값 배열이 같고 재귀가되도록 주장하십시오. 키도 고유 한지도도 포함하도록이를 확장 할 수 있습니다. (그러나 이것을 세트로 확장하면 트리 동형 문제 문제가 발생합니다. http://logic.pdmi.ras.ru/~smal/files/smal_jass08_slides.pdf다행스럽게도 일반적인 그래프 동 형사상만큼 어렵지 않습니다. 실제로이를 해결하기위한 O (#vertices) 알고리즘이 있지만 효율적으로 수행하기에는 매우 복잡 할 수 있습니다. 병리학 적 사례는 보이지 않는 것으로 보이는 많은 물체로 구성된 세트를 가지고 있지만 더 자세히 살펴볼 때 그 물체 중 일부는 더 깊이 파고들 때 다를 수 있습니다. 해싱을 사용하여 거의 모든 경우를 거부하여이 문제를 해결할 수도 있습니다.)


옵션 4 : (2016 년 편집 계속)

이것은 대부분의 객체에서 작동합니다.

function deepEquals(a,b) {
    if (a instanceof Array && b instanceof Array)
        return arraysEqual(a,b);
    if (Object.getPrototypeOf(a)===Object.prototype && Object.getPrototypeOf(b)===Object.prototype)
        return objectsEqual(a,b);
    if (a instanceof Map && b instanceof Map)
        return mapsEqual(a,b);        
    if (a instanceof Set && b instanceof Set)
        throw "Error: set equality by hashing not implemented."
    if ((a instanceof ArrayBuffer || ArrayBuffer.isView(a)) && (b instanceof ArrayBuffer || ArrayBuffer.isView(b)))
        return typedArraysEqual(a,b);
    return a==b;  // see note[1] -- IMPORTANT
}

function arraysEqual(a,b) {
    if (a.length!=b.length)
        return false;
    for(var i=0; i<a.length; i++)
        if (!deepEquals(a[i],b[i]))
            return false;
    return true;
}
function objectsEqual(a,b) {
    var aKeys = Object.getOwnPropertyNames(a);
    var bKeys = Object.getOwnPropertyNames(b);
    if (aKeys.length!=bKeys.length)
        return false;
    aKeys.sort();
    bKeys.sort();
    for(var i=0; i<aKeys.length; i++)
        if (aKeys[i]!=bKeys[i]) // keys must be strings
            return false;
    return deepEquals(aKeys.map(k=>a[k]), aKeys.map(k=>b[k]));
}
function mapsEqual(a,b) {
    if (a.size!=b.size)
        return false;
    var aPairs = Array.from(a);
    var bPairs = Array.from(b);
    aPairs.sort((x,y) => x[0]<y[0]);
    bPairs.sort((x,y) => x[0]<y[0]);
    for(var i=0; i<a.length; i++)
        if (!deepEquals(aPairs[i][0],bPairs[i][0]) || !deepEquals(aPairs[i][1],bPairs[i][1]))
            return false;
    return true;
}
function typedArraysEqual(a,b) {
    a = new Uint8Array(a);
    b = new Uint8Array(b);
    if (a.length != b.length)
        return false;
    for(var i=0; i<a.length; i++)
        if (a[i]!=b[i])
            return false;
    return true;
}

데모 (일반적으로 테스트되지 않음) :

var nineTen = new Float32Array(2);
nineTen[0]=9; nineTen[1]=10;
deepEquals(
    [[1,[2,3]], 4, {a:5,b:6}, new Map([['c',7],['d',8]]), nineTen],
    [[1,[2,3]], 4, {b:6,a:5}, new Map([['d',8],['c',7]]), nineTen]
)

(측면 노트 :지도는 es6 사전입니다. O (1) 또는 O (log (N)) 조회 성능이 있는지 확인할 수는 없지만 주문을 추적한다는 의미에서 '순서'입니다. 키-값 쌍이 삽입 된 요소이지만 요소가 다른 순서로 삽입 된 경우 두 개의 맵이 동일한 지 여부에 대한 의미는 모호합니다. 두 맵이 동일한 것으로 간주되는 deepEquals 아래에 샘플 구현을 제공합니다. 요소가 다른 순서로 삽입 된 경우)

(참고 [1] : 중요 : 평등의 개념 : 언급 된 행을 사용자 정의 평등 개념으로 재정의 할 수도 있습니다. 사용자 정의 평등 개념으로 표시되는 다른 기능에서도 변경해야합니다. NaN == NaN을 원하지 않습니까? 기본적으로는 그렇지 않습니다. 0 == '0'과 같이 더 이상한 것들이 있습니다. 두 객체가 동일한 객체 인 경우에만 동일한 것으로 간주합니까? https://stackoverflow.com/a/5447170/711085를 참조 하십시오 사용하는 평등 개념을 문서화해야합니다.)

위의 내용을 WeakMaps, WeakSets로 확장 할 수 있어야합니다. DataViews로 확장하는 것이 의미가 있는지 확실하지 않습니다. 아마도 RegExps 등으로 확장 할 수 있어야합니다.

확장하면 불필요한 비교를 많이한다는 것을 알게됩니다. 여기에서 type이전에 정의한 기능 (솔루션 # 2)이 유용 할 수 있습니다. 그러면 즉시 파견 할 수 있습니다. 유형을 나타내는 문자열의 오버 헤드 가치가 있는지 (아마도 후드에서 어떻게 작동하는지 확실하지 않은지) 당신에게 달려 있습니다. 그런 다음 디스패처, 즉 함수 deepEquals를 다음과 같이 다시 작성할 수 있습니다 .

var dispatchTypeEquals = {
    number: function(a,b) {...a==b...},
    array: function(a,b) {...deepEquals(x,y)...},
    ...
}
function deepEquals(a,b) {
    var typeA = extractType(a);
    var typeB = extractType(a);
    return typeA==typeB && dispatchTypeEquals[typeA](a,b);
}

jQuery에는 배열을 비교하는 방법이 없습니다. 그러나 Underscore 라이브러리 (또는 유사한 Lodash 라이브러리)에는 이러한 메소드가 있습니다 : isEqual , 객체 리터럴과 같은 다양한 다른 경우도 처리 할 수 ​​있습니다. 제공된 예를 고수하려면 :

var a=[1,2,3];
var b=[3,2,1];
var c=new Array(1,2,3);

alert(_.isEqual(a, b) + "|" + _.isEqual(b, c));

그런데 Underscore에는 jQuery가 누락 된 다른 많은 방법이 있으므로 jQuery를 보완하는 훌륭한 방법입니다.

편집 : 주석에서 지적했듯이 위의 두 배열 모두 동일한 순서로 요소가있는 경우에만 작동합니다.

_.isEqual([1,2,3], [1,2,3]); // true
_.isEqual([1,2,3], [3,2,1]); // false

다행히 Javascript에는이 정확한 문제를 해결하기위한 기본 제공 방법이 있습니다 sort.

_.isEqual([1,2,3].sort(), [3,2,1].sort()); // true

숫자 및 문자열과 같은 기본 값의 경우 쉬운 솔루션입니다.

a = [1,2,3]

b = [3,2,1]

a.sort().toString() == b.sort().toString() 

호출 sort()은 요소의 순서가 중요하지 않게합니다. toString()호출은 쉼표로 구분 된 값으로 문자열을 작성하므로 두 문자열이 동일한 지 테스트 할 수 있습니다.


JavaScript 버전 1.6을 사용하면 다음과 같이 쉽습니다.

Array.prototype.equals = function( array ) {
  return this.length == array.length && 
         this.every( function(this_i,i) { return this_i == array[i] } )  
  }

예를 들어, [].equals([])gives true, [1,2,3].equals( [1,3,2] )yields false입니다.


이것이 매우 단순 해 보이지만 때로는 실제로 유용합니다. 두 배열의 항목이 동일하고 순서가 동일한 지 확인하려면 다음을 시도하십시오.

[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

그러나 다음과 같은 모드 고급 경우에는 작동하지 않습니다.

[[1,2],[3]].toString() == [[1],[2,3]].toString()
true

필요한 것에 달려 있습니다.


Tim James 답변 과 Fox32의 의견을 바탕으로 다음은 두 개의 null이 같지 않다는 가정하에 null을 확인해야합니다.

function arrays_equal(a,b) { return !!a && !!b && !(a<b || b<a); }

> arrays_equal([1,2,3], [1,3,4])
false
> arrays_equal([1,2,3], [1,2,3])
true
> arrays_equal([1,3,4], [1,2,3])
false
> arrays_equal(null, [1,2,3])
false
> arrays_equal(null, null)
false

jQuery에는 재귀 비교를위한 그러한 방법 있습니다.

자체 제작 된 범용 엄격한 평등 검사는 다음과 같습니다.

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.');

배열의 크기를 확인한 후 for 루프로 각 값을 확인하십시오.

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

사용 map()하여 reduce():

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

lodash를 사용 중이고 배열을 수정하지 않으려는 경우 _.xor () 함수를 사용할 수 있습니다 . 두 배열을 집합으로 비교하고 차이가 포함 된 집합을 반환합니다. 이 차이의 길이가 0이면 두 배열은 기본적으로 동일합니다.

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

이 작업을 수행하는 쉬운 방법은 없습니다. 나는 이것도 필요했지만 두 변수를 가지고 평등을 테스트 할 수있는 함수를 원했다. 여기에는 객체가 아닌 값, 객체, 배열 및 모든 수준의 중첩이 포함됩니다.

귀하의 질문에서 배열의 값 순서를 무시하고 싶다고 언급했습니다. 내 솔루션은 본질적으로 그렇게하지는 않지만 평등을 비교하기 전에 배열을 정렬하여 얻을 수 있습니다.

또한 [1,2] === [ "1", 2]가되도록 비 객체를 문자열로 캐스트하는 옵션을 원했습니다.

내 프로젝트는 UnderscoreJ를 사용하기 때문에 독립형 함수가 아닌 믹스 인으로하기로 결정했습니다.

http://jsfiddle.net/nemesarial/T44W4/ 에서 테스트 할 수 있습니다

내 mxin은 다음과 같습니다.

_.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);

당신은 확인하려면 어떤지 객체의 배열 과 순서는 중요하지 않습니다, 즉

areEqual([{id: "0"}, {id: "1"}], [{id: "1"}, {id: "0"}]) // true

먼저 배열을 정렬해야합니다. lodash가 결합하여 당신이 필요한 모든 도구가 sortBy와를 isEqual:

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

편집 : sortBy새 배열을 반환 하므로 정렬하기 전에 배열을 복제 할 필요가 없습니다. 원래 배열은 변경되지 않습니다.

lodash의 isEqual경우 순서가 중요 합니다. 위 예제는 각 배열에 먼저 적용되지 않은 false경우 반환 합니다 sortBy.


가능한 모든 것을 처리하고 객체의 구조에서 자체를 참조합니다. 코드 끝에서 예제를 볼 수 있습니다.

var deepCompare = (function() {
    function internalDeepCompare (obj1, obj2, objects) {
        var i, objPair;

        if (obj1 === obj2) {
            return true;
        }

        i = objects.length;
        while (i--) {
            objPair = objects[i];
            if (  (objPair.obj1 === obj1 && objPair.obj2 === obj2) ||
                  (objPair.obj1 === obj2 && objPair.obj2 === obj1)  ) {                          
                return true;
            }                    
        }
        objects.push({obj1: obj1, obj2: obj2});

        if (obj1 instanceof Array) {
            if (!(obj2 instanceof Array)) {
                return false;
            }

            i = obj1.length;

            if (i !== obj2.length) {
               return false; 
            }

            while (i--) {
                if (!internalDeepCompare(obj1[i], obj2[i], objects)) {
                    return false;
                }
            }
        }
        else {
            switch (typeof obj1) {
                case "object":                
                    // deal with null
                    if (!(obj2 && obj1.constructor === obj2.constructor)) {
                        return false;
                    }

                    if (obj1 instanceof RegExp) {
                        if (!(obj2 instanceof RegExp && obj1.source === obj2.source)) {
                            return false;
                        }
                    }                 
                    else if (obj1 instanceof Date) {
                        if (!(obj2 instanceof Date && obj1.getTime() === obj2.getTime())) {
                            return false;
                        }
                    } 
                    else {    
                        for (i in obj1) {
                            if (obj1.hasOwnProperty(i)) {       
                                if (!(obj2.hasOwnProperty(i) && internalDeepCompare(obj1[i], obj2[i], objects))) {
                                    return false;
                                }
                            }
                        }         
                    }
                    break;
                case "function": 
                    if (!(typeof obj2 === "function" && obj1+"" === obj2+"")) {
                        return false;
                    }
                    break;
                default:                 //deal with NaN 
                    if (obj1 !== obj2 && obj1 === obj1 && obj2 === obj2) {
                        return false;            
                    }
            }
        }

        return true;
    }

    return function (obj1, obj2) {
        return internalDeepCompare(obj1, obj2, []);    
    };
}());

/*    
var a = [a, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null],
    b = [b, undefined, new Date(10), /.+/, {a:2}, function(){}, Infinity, -Infinity, NaN, 0, -0, 1, [4,5], "1", "-1", "a", null];
deepCompare(a, b);
*/

이 방법은 짜증이 나지만 참조를 위해 여기에 남겨 두었으므로 다른 사람들은이 경로를 피하십시오.


@ninjagecko의 옵션 1을 사용하는 것이 가장 효과적이었습니다.

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

또한 배열 프로토 타입에 이것을 추가하고 다른 인수가 배열인지 확인하기 때문에 null 및 undefined case도 처리합니다.


var a= [1, 2, 3, '3'];
var b = [1, 2, 3];

var c = a.filter(function (i) { return ! ~b.indexOf(i); });

alert(c.length);

참고 URL : https://stackoverflow.com/questions/3115982/how-to-check-if-two-arrays-are-equal-with-javascript

반응형