itsource

두 어레이가 JavaScript와 동일한지 확인하는 방법

mycopycode 2022. 11. 5. 17:28
반응형

두 어레이가 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는 이를 위한 방법을 제공합니까?

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★는 사용하지 말아 주세요.stringify 않다< >.

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

[variable changelog: option 4의 버그 수정: js 개체에 대한 전체 순서가 없음(제외된 경우에도)NaN!=NaN ★★★★★★★★★★★★★★★★★」'5'==5 )'5'===5,'2'<3는 사용할 수 ..sort(cmpFunc) (Map.keys() (단,Object.keys(obj)]('어느 쪽인가')

옵션 1

는 거의 사용할 수 . 단, 그 이외의 에는 사용할 수 있습니다.null!==undefined 다 으로 변환됩니다.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은{1:2,3:4} 않을 수도 {3:4,1:2}이것은 실장에 따라 다르며, 사양은 어떠한 보증도 하지 않습니다.[2017년 갱신:실제로 ES6 사양에서는 객체 키가 1) 정수 속성 2) 정의된 순서대로, 3) 정의된 순서대로 반복됨을 보증합니다.따라서 JSON.stringify 구현이 이를 따를 경우 동일한 개체(=== 의미에서는 동일하지만 == 의미에서는 반드시 그렇지 않음)가 동일한 값으로 문자열화됩니다.더 많은 연구가 필요했습니다.그래서 역순으로 성질을 가진 사물의 사악한 복제품을 만들 수 있을 것 같은데, 우연히 그런 일이 일어나리라고는 상상도 할 수 없어...] 적어도 Chrome에서는 JSON.stringify 함수는 정의된 순서대로 키를 반환하는 경향이 있지만(적어도 제가 알기로는), 이 동작은 언제든지 변경될 수 있으므로 신뢰할 수 없습니다. 목록에서 개체를 사용하지 않도록 선택하면 올바르게 작동합니다.목록에 모두 고유한 ID를 가진 개체가 있는 경우 다음을 수행할 수 있습니다.a1.map(function(x)}{return {id:x.uniqueId}})목록에 임의의 개체가 있는 경우 옵션 #2를 읽을 수 있습니다.)

이는 중첩된 어레이에도 적용됩니다.

그러나 이러한 문자열을 만들고 가비지를 수집하는 데 드는 오버헤드로 인해 다소 비효율적입니다.


옵션 2

이전 버전 1 솔루션:

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

// Demo:

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
<!--

More "proper" option, which you can override to deal with special cases (like regular objects and null/undefined and custom objects, if you so desire):

To use this like a regular function, do:

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

Demo:

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


옵션 3

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

//Examples:

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
/*
If you wanted to apply this to JSON-like data structures with js Objects, you could do so. Fortunately we're guaranteed that all objects keys are unique, so iterate over the objects OwnProperties and sort them by key, then assert that both the sorted key-array is equal and the value-array are equal, and just recurse. We CANNOT extend the sort-then-compare method with Maps as well; even though Map keys are unique, there is no total ordering in ecmascript, so you can't sort them... but you CAN query them individually (see the next section Option 4). (Also if we extend this to Sets, we run into the tree isomorphism problem http://logic.pdmi.ras.ru/~smal/files/smal_jass08_slides.pdf - fortunately it's not as hard as general graph isomorphism; there is in fact an O(#vertices) algorithm to solve it, but it can get very complicated to do it efficiently. The pathological case is if you have a set made up of lots of seemingly-indistinguishable objects, but upon further inspection some of those objects may differ as you delve deeper into them. You can also work around this by using hashing to reject almost all cases.)
*/
<!--
**edit**: It's 2016 and my previous overcomplicated answer was bugging me. This recursive, imperative "recursive programming 101" implementation keeps the code really simple, and furthermore fails at the earliest possible point (giving us efficiency). It also doesn't generate superfluous ephemeral datastructures (not that there's anything wrong with functional programming in general, but just keeping it clean here).

If we wanted to apply this to a non-empty arrays of arrays, we could do seriesOfArrays.reduce(arraysEqual).

This is its own function, as opposed to using Object.defineProperties to attach to Array.prototype, since that would fail with a key error if we passed in an undefined value (that is however a fine design decision if you want to do so).

This only answers OPs original question.
-->


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

이것은 대부분의 오브젝트에서 동작합니다.

const STRICT_EQUALITY_BROKEN = (a,b)=> a===b;
const STRICT_EQUALITY_NO_NAN = (a,b)=> {
    if (typeof a=='number' && typeof b=='number' && ''+a=='NaN' && ''+b=='NaN')
        // isNaN does not do what you think; see +/-Infinity
        return true;
    else
        return a===b;
};
function deepEquals(a,b, areEqual=STRICT_EQUALITY_NO_NAN, setElementsAreEqual=STRICT_EQUALITY_NO_NAN) {
    /* compares objects hierarchically using the provided 
       notion of equality (defaulting to ===);
       supports Arrays, Objects, Maps, ArrayBuffers */
    if (a instanceof Array && b instanceof Array)
        return arraysEqual(a,b, areEqual);
    if (Object.getPrototypeOf(a)===Object.prototype && Object.getPrototypeOf(b)===Object.prototype)
        return objectsEqual(a,b, areEqual);
    if (a instanceof Map && b instanceof Map)
        return mapsEqual(a,b, areEqual);        
    if (a instanceof Set && b instanceof Set) {
        if (setElementsAreEqual===STRICT_EQUALITY_NO_NAN)
            return setsEqual(a,b);
        else
            throw "Error: set equality by hashing not implemented because cannot guarantee custom notion of equality is transitive without programmer intervention."
    }
    if ((a instanceof ArrayBuffer || ArrayBuffer.isView(a)) && (b instanceof ArrayBuffer || ArrayBuffer.isView(b)))
        return typedArraysEqual(a,b);
    return areEqual(a,b);  // see note[1] -- IMPORTANT
}

function arraysEqual(a,b, areEqual) {
    if (a.length!=b.length)
        return false;
    for(var i=0; i<a.length; i++)
        if (!deepEquals(a[i],b[i], areEqual))
            return false;
    return true;
}
function objectsEqual(a,b, areEqual) {
    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 (!areEqual(aKeys[i],bKeys[i])) // keys must be strings
            return false;
    return deepEquals(aKeys.map(k=>a[k]), aKeys.map(k=>b[k]), areEqual);
}
function mapsEqual(a,b, areEqual) { // assumes Map's keys use the '===' notion of equality, which is also the assumption of .has and .get methods in the spec; however, Map's values use our notion of the areEqual parameter
    if (a.size!=b.size)
        return false;
    return [...a.keys()].every(k=> 
        b.has(k) && deepEquals(a.get(k), b.get(k), areEqual)
    );
}
function setsEqual(a,b) {
    // see discussion in below rest of StackOverflow answer
    return a.size==b.size && [...a.keys()].every(k=> 
        b.has(k)
    );
}
function typedArraysEqual(a,b) {
    // we use the obvious notion of equality for binary data
    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;
}
Demo (not extensively tested):

var nineTen = new Float32Array(2);
nineTen[0]=9; nineTen[1]=10;

> deepEquals(
    [[1,[2,3]], 4, {a:5,'111':6}, new Map([['c',7],['d',8]]), nineTen],
    [[1,[2,3]], 4, {111:6,a:5}, new Map([['d',8],['c',7]]), nineTen]
)
true

> deepEquals(
    [[1,[2,3]], 4, {a:'5','111':6}, new Map([['c',7],['d',8]]), nineTen],
    [[1,[2,3]], 4, {111:6,a:5}, new Map([['d',8],['c',7]]), nineTen],
    (a,b)=>a==b
)
true

「 」를 하고 있는 는, 의 점에 해 주세요.==평등의 개념, 그렇다면 거짓된 가치와 강요가 그것을 의미한다는 것을 안다.==평등은 과도적이지 않습니다.를 들어, 「」입니다.''==0 ★★★★★★★★★★★★★★★★★」0=='0'''!='0'이것은 집합과 관련이 있다: 나는 평등 집합의 개념을 의미 있는 방법으로 덮어쓸 수 없다고 생각한다. equality [Set equality의 개념을 ,=== 위의 , 하는 경우==: 지렁이 통조림 따다사용자에게 도메인(해시(a))에 해시함수를 정의하도록 강요한 경우에도!=(b)는 a!=b)그게 도움이 될지 모르겠는데...) 할 수 , O(N^2)의 할 수 있습니다.==정렬과 로 통과시킨 후 두 O 내의 O-N-N-N-N은 O(N)입니다.==, 또 「상대방」, 「상대방」도 있습니다.!=이렇게 짝지어지지 않은 모든 것에 영향을 주지만, 만약 당신이 강요를 한다면 여전히 런타임 오류를 던져야 할 것이다.또한 https://developer.mozilla.org/en-US/docs/Glossary/Falsy 및 Truthy 값(NaN==NaN 제외)을 사용하면 이상할 수 있습니다.단, 세트 전용입니다.이것은 보통 대부분의 동종 데이터 유형 집합에서 문제가 되지 않습니다.

집합에서 재귀적 균등의 복잡성을 요약하려면:

  • 동일성 설정은 트리 동형 문제 http://logic.pdmi.ras.ru/~smal/files/smal_jass08_smal.pdf입니다만, 조금 더 심플합니다.
  • = ?을 A = ?의 를 설정합니다.B.has(k) for every k in A으로 사용하다===(-syslogit)[1,2,3]!==[1,2,3] 평등 , )이.deepEquals([1,2,3],[1,2,3]) == true) 、 、 、 、 、 2 。new Set([[1,2,3]]) 않을 것이다.
  • 만약 당신이 사용하는 평등의 재귀적 개념이 1) 재귀적 (a=b는 b=a를 의미함) 그리고 2) 대칭적 (a=a) 그리고 3) 추이적 (a=b와 b=c는 a=c를 의미함)이라면, 이것은 동등성 클래스의 정의이다.
  • equal == 연산자는 명백히 이러한 속성 중 많은 부분을 따르지 않습니다.
  • emascript의 strict equality === 연산자조차 이러한 속성을 따르지 않습니다. emascript의 strict equality 비교 알고리즘에는 NaN이 있기 때문입니다!=NaN; 이것이 많은 네이티브 데이터형이 좋아하는 이유입니다.Set ★★★★★★★★★★★★★★★★★」Map되는 경우 NaN이 NaN은 NaN이 키 NaN으로 표시되는 경우 NaN은 NaN으로 간주됩니다.
  • 우리가 재귀적 집합의 평등이 실제로 과도적이고 반사적이며 대칭적인 것을 강요하고 확실히 하는 한, 우리는 끔찍하게 잘못된 일이 일어나지 않도록 확실히 할 수 있다.
    • 그러면 모든 것을 랜덤하게 재귀적으로 비교함으로써 O(N^2) 비교를 할 수 있는데, 이는 매우 비효율적입니다.가 할 수 .setKeys.sort((a,b)=> /*some comparison function*/)==0 및 0=='에는 전체 '!='ecmascript0 =='0')에는 없습니다.하지만, 분명히 고귀한 목표가 될 수 있는 것을 스스로 정의할 수 있다고 생각합니다.
    • 우리는 할 수 ..toString 또는 는yJSON.stringify모든 요소가 도움이 됩니다.런음 그러면 잠재적으로 false-positive(다른 두 개의 문자열이 동일한 JSON 표현이 아닌)의 동등성 클래스가 제공됩니다.
      • 그러나, 같은 것을 시리얼화하면, 그 서브셋을 몇번이나 시리얼화 하는 것은 매우 비효율적이기 때문에, 그 자체의 퍼포먼스 문제가 발생합니다. 네스트 해 보세요.Set 각 는 O의 다른 시리얼화. 모든 노드가 O(깊이)의 다른 시리얼라이제이션에 속합니다.
      • 그것이 문제가 아니더라도 모든 시리얼화 '힌트'가 동일하면 최악의 퍼포먼스는 O(N!)가 됩니다.

따라서 위의 구현에서는 항목이 단순 ===(재귀 ===이 아님)인 경우 집합이 동일함을 선언합니다., false는 됩니다.new Set([1,2,3]) ★★★★★★★★★★★★★★★★★」new Set([1,2,3])만약 당신이 무엇을 하고 있는지 알고 있다면, 당신은 약간의 노력으로 코드의 그 부분을 다시 쓸 수 있습니다.

(사이드노트:지도는 es6 사전입니다.O(1)와 O(log(N) 중 어느 쪽을 참조할지는 알 수 없지만, 어느 경우든 키와 값의 페어가 삽입된 순서를 추적하고 있다는 점에서 '순서'가 되어 있습니다.그러나 요소가 다른 순서로 삽입된 경우 두 맵이 동일해야 하는지 여부에 대한 의미는 모호합니다.2개의 맵에 다른 순서로 삽입되어 있어도 동일하게 간주하는 deepEquals의 구현 예를 다음에 나타냅니다.)

(주 [1]: 중요: 평등 개념: 기재된 행을 커스텀 평등 개념으로 덮어쓸 수 있습니다.이러한 행은 표시되는 다른 함수에서도 변경해야 합니다.예를 들어 NaN==NaN을 원하십니까?기본적으로는 그렇지 않습니다.0=='0'과 같은 더 이상한 것들이 있다.두 개체가 메모리 내에서 동일한 개체인 경우에만 동일한 개체라고 생각하십니까?https://stackoverflow.com/a/5447170/711085 를 참조해 주세요.사용하는 평등에 대한 개념을 문서화해야 합니다.또, 순진하게 사용하는 다른 회답에 주의해 주세요..toString ★★★★★★★★★★★★★★★★★」.sort ...을도 한다.라는 사실에 기도할 수도 있다.0!=-0그러나 거의 모든 데이터 유형 및 JSON 직렬화에 대해 0으로 동일하고 정규화할 수 있는 것으로 간주됩니다. -0==0은 동등성의 개념뿐만 아니라 NaN과 같은 표의 대부분의 다른 사항에서도 문서화되어야 하는지 여부입니다.

위 내용을 WeakMaps, WeakSets로 확장할 수 있습니다.Data Views로 확장하는 것이 타당한지 잘 모르겠습니다.또한 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에는 배열을 비교하는 메서드가 없습니다.그러나 언더스코어 라이브러리(또는 이와 동등한 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));

덧붙여서, 언더스코어에는 jQuery에 없는 다른 많은 메서드가 있기 때문에, jQuery에 매우 적합합니다.

편집: 코멘트에서 지적한 바와 같이, 위는 양쪽 어레이의 요소가 같은 순서로 되어 있는 경우에만 기능합니다.즉, 다음과 같습니다.

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

는 이하기 위한 .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([])true와 동시에 , 「」를 참조해 주세요.[1,2,3].equals( [1,3,2] ) 율율false.

이것이 매우 간단해 보일지라도, 가끔은 정말 유용합니다.2개의 어레이가 같은 아이템을 가지고 있고, 같은 순서로 되어 있는지를 확인하는 것만이 필요한 경우는, 다음과 같이 시험해 주세요.

[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의 코멘트에 근거해, 2개의 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.');

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

어레이 크기를 확인한 후 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)
    );
}

오브젝트 배열의 동일성과 순서는 중요하지 않습니다.

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순서는 중요합니다.위의 예는 반환됩니다.falsesortBy는 각 어레이에 먼저 적용되지 않습니다.

이 방법은 형편없지만 다른 사람이 이 경로를 피하도록 참고용으로 남겨두었습니다.


@ninjagecko의 Option 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과 정의되지 않은 대소문자도 처리합니다.이 대소문자를 어레이의 프로토타입에 추가하고 다른 인수도 어레이인지 확인합니다.

이것을 하는 쉬운 방법은 없다.이것도 필요했지만, 어떤 두 변수를 취해서 동등성을 검정할 수 있는 함수를 원했습니다.여기에는 객체 이외의 값, 객체, 배열 및 모든 수준의 중첩이 포함됩니다.

질문에서 배열의 값 순서를 무시하고 싶다고 말씀하셨습니다.내 솔루션에서는 본질적으로 그렇지 않지만 어레이를 정렬하여 동등성을 비교함으로써 달성할 수 있습니다.

또한 [1,2]===["1,2"]가 되도록 현악기에 고정되지 않는 것을 캐스팅할 수 있는 옵션도 원했습니다.

프로젝트에서는 Underscore Js를 사용하고 있기 때문에 스탠드아론 기능이 아닌 믹스인으로 하기로 했습니다.

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

그것은 가능한 모든 것을 처리하고 심지어 물체의 구조에서 자신을 참조합니다.이 예는 코드 끝에 있습니다.

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);
*/
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

반응형