itsource

JavaScript에서 어레이를 비교하는 방법

mycopycode 2022. 10. 25. 21:32
반응형

JavaScript에서 어레이를 비교하는 방법

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★상적이 아닌, 려 nothing nothing nothing nothing nothing nothing nothing nothing nothing nothing nothing nothingtrue 및 「」의 경우는,false 다를까비교 연산자가 하지 않는것 같아요.당연히 비교 연산자가 작동하지 않는 것 같습니다.

var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2);    // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2));    // Returns true

JSON은 각 어레이를 인코딩합니다만, 각 값을 반복하지 않고 어레이를 간단하게 비교할 수 있는 더 빠르고 "더 나은" 방법이 있을까요?

어레이를 비교하려면 어레이를 반복하여 모든 값을 비교합니다.

어레이 비교:

// Warn if overriding existing method
if(Array.prototype.equals)
    console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
    // if the other array is a falsy value, return
    if (!array)
        return false;

    // compare lengths - can save a lot of time 
    if (this.length != array.length)
        return false;

    for (var i = 0, l=this.length; i < l; i++) {
        // Check if we have nested arrays
        if (this[i] instanceof Array && array[i] instanceof Array) {
            // recurse into the nested arrays
            if (!this[i].equals(array[i]))
                return false;       
        }           
        else if (this[i] != array[i]) { 
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;   
        }           
    }       
    return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});

사용방법:

[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;

"그러나 스트링을 비교하는 것이 훨씬 빠릅니다.루프가 없습니다."그럼 루프가 있다는 것을 알아두세요.어레이를 문자열로 변환하는 첫 번째 재귀 루프와 두 번째 재귀 루프 두 개의 문자열을 비교합니다.따라서 이 방법은 문자열 사용보다 빠릅니다.

저는 더 많은 양의 데이터를 항상 객체가 아닌 어레이에 저장해야 합니다.그러나 객체를 사용하는 경우 부분적인 비교도 가능합니다.
을 사용하다

오브젝트 비교:

위에서 설명한 바와 같이 두 객체 인스턴스는 현재 동일한 데이터를 포함하더라도 결코 동일하지 않습니다.

({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666})  //false

예를 들어 개체 내에 개인 변수가 있을 수 있기 때문에 여기에는 이유가 있습니다.

그러나 객체 구조를 사용하여 데이터를 저장하는 경우 다음과 같은 비교가 가능합니다.

Object.prototype.equals = function(object2) {
    //For the first loop, we only check for types
    for (propName in this) {
        //Check for inherited methods and properties - like .equals itself
        //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
        //Return false if the return value is different
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        //Check instance type
        else if (typeof this[propName] != typeof object2[propName]) {
            //Different types => not equal
            return false;
        }
    }
    //Now a deeper check using other objects property names
    for(propName in object2) {
        //We must check instances anyway, there may be a property that only exists in object2
            //I wonder, if remembering the checked values from the first loop would be faster or not 
        if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
            return false;
        }
        else if (typeof this[propName] != typeof object2[propName]) {
            return false;
        }
        //If the property is inherited, do not check any more (it must be equa if both objects inherit it)
        if(!this.hasOwnProperty(propName))
          continue;
        
        //Now the detail check and recursion
        
        //This returns the script back to the array comparing
        /**REQUIRES Array.equals**/
        if (this[propName] instanceof Array && object2[propName] instanceof Array) {
                   // recurse into the nested arrays
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
                   // recurse into another objects
                   //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
           if (!this[propName].equals(object2[propName]))
                        return false;
        }
        //Normal value comparison for strings and numbers
        else if(this[propName] != object2[propName]) {
           return false;
        }
    }
    //If everything passed, let's say YES
    return true;
}  

단, 이것은 JSON을 클래스 인스턴스 등의 데이터가 아닌 데이터와 비교하기 위한 것입니다.더 복잡한 사물을 비교하고 싶다면 이 답을 보세요. 매우 함수입니다.
이 기능을 사용하려면Array.equals원래 기능을 약간 편집해야 합니다.

...
    // Check if we have nested arrays
    if (this[i] instanceof Array && array[i] instanceof Array) {
        // recurse into the nested arrays
        if (!this[i].equals(array[i]))
            return false;
    }
    /**REQUIRES OBJECT COMPARE**/
    else if (this[i] instanceof Object && array[i] instanceof Object) {
        // recurse into another objects
        //console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
        if (!this[i].equals(array[i]))
            return false;
        }
    else if (this[i] != array[i]) {
...

기능 모두 작은 테스트 도구를 만들었습니다.

와 스: 스: with: bonus with with:indexOf ★★★★★★★★★★★★★★★★★」contains

Samy Bencherif는 중첩된 배열에서 특정 개체를 검색할 경우에 사용할 수 있는 유용한 함수를 준비했습니다. https://jsfiddle.net/SamyBencherif/8352y6yw/

이것은 스칼라 어레이에서만 동작하지만(아래 참고 참조), 짧은 코드입니다.

array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})

위와 동일하지만 ECMAScript 6 / CoffeeScript / TypeScript with Arrow 함수:

array1.length === array2.length && array1.every((value, index) => value === array2[index])

서 '는 직접 할 수 입니다.===숫자, 문자열, 기준 오브젝트, 기준 함수.비교 연산자에 대한 자세한 내용은 MDN 참조를 참조하십시오).

갱신하다

코멘트에서 읽은 바로는 어레이를 정렬하여 비교함으로써 정확한 결과를 얻을 수 있습니다.

const array2Sorted = array2.slice().sort();
array1.length === array2.length && array1.slice().sort().every(function(value, index) {
    return value === array2Sorted[index];
});

예:

array1 = [2,3,1,4];
array2 = [1,2,3,4];

위의 됩니다.true

어레이/오브젝트 헤비 코딩 프로젝트에는 언더스코어 라이브러리를 사용합니다.언더스코어 및 Lodash에서는 어레이와 오브젝트를 비교할 때 다음과 같이 표시됩니다.

_.isEqual(array1, array2)   // returns a boolean
_.isEqual(object1, object2) // returns a boolean

이것은 JSON stringify를 사용하여 실행하는 가장 간단한 방법이며 상황에 따라서는 최적의 솔루션이 될 수 있습니다.

JSON.stringify(a1) === JSON.stringify(a2);

오브젝트가 됩니다.a1 ★★★★★★★★★★★★★★★★★」a2현을 만들어 비교가 가능합니다.대부분의 경우 순서는 중요합니다.이 순서는 위의 답변 중 하나에 나타난 정렬 알고리즘을 사용하여 객체를 정렬할 수 있기 때문입니다.

더 이상 개체를 비교하는 것이 아니라 개체의 문자열 표현이라는 점에 유의하십시오.당신이 원하는 게 아닐 수도 있어요.

원래 질문의 정신으로:

두 어레이를 비교하고 싶은데...이상적이고 효율적으로.과장된 것은 없고, 같으면 진실이고, 같지 않으면 거짓이다.

여기서 제안하는 간단한 제안 중 몇 가지에 대해 퍼포먼스 테스트를 실시해 왔습니다.다음의 결과(빠른 것까지).

반면(67%) Tim Down에 의해

var i = a1.length;
while (i--) {
    if (a1[i] !== a2[i]) return false;
}
return true

사용자별(69%)2782196

a1.every((v,i)=> v === a2[i]);

DEI에 의한 삭감(74%)

a1.reduce((a, b) => a && a2.includes(b), true);

Gaizka Allende & vivek의 Join & ToString(78%)

a1.join('') === a2.join('');

a1.toString() === a2.toString();

Half toString (90%) (Victor Palomo)

a1 == a2.toString();

라덱으로 문자열화(100%)하다

JSON.stringify(a1) === JSON.stringify(a2);

다음 예시는 어레이가 정렬된 단차원 어레이로 가정하고 있습니다. .length벤치마크에 ).a1.length === a2.length10%를 차지하다각 솔루션의 속도와 제한을 파악하여 고객에게 가장 적합한 솔루션을 선택하십시오.

관련 없는 메모: 사람들이 이 질문에 대한 완전히 합법적인 답변에 대해 모든 트리거링에 만족하는 John Waynes를 투표 버튼에 올리는 것을 보는 것은 흥미롭다.

실용적인 방법

특정 구현이 "올바른" 솔루션과 대조적으로 "올바른"("올바른") 것이라면 "The Right Way™"라고 말하는 것은 잘못된 것이라고 생각합니다.Tomash의 솔루션은 문자열 기반 어레이 비교에 비해 확연히 개선되었지만 객관적으로 "올바른" 것은 아닙니다.어쨌거나 뭐가 옳은걸까?가장 빠른가요?이게 가장 유연해요?그게 가장 이해하기 쉬워요?디버깅이 가장 빠릅니까?조작을 최소한으로 억제하고 있습니까?부작용이 있나요?어떤 솔루션도 최고의 솔루션을 얻을 수 없습니다.

Tomash's는 그의 해결책이 빠르다고 말할 수 있지만 나는 또한 불필요하게 복잡하다고 말할 수 있다.이 솔루션은 네스트 여부에 관계없이 모든 어레이에서 작동하는 올인원 솔루션입니다.실제로 어레이를 입력으로 받아들이는 것뿐만 아니라 "유효한" 답변을 제공하려고 합니다.


범용성이 뛰어난 제품

내 대답은 그 문제에 대해 다르게 접근할 것이다.인 것으로 arrayCompare어레이의 스텝에만 관계하는 순서입니다.ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ'arrayEqual ★★★★★★★★★★★★★★★★★」arrayDeepEqual,syslogs

// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
  x === undefined && y === undefined
    ? true
    : Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)

내 생각에, 가장 좋은 종류의 코드는 코멘트가 필요하지도 않고, 이것도 예외는 아니다.여기에는 거의 아무런 노력 없이 이 절차의 동작을 이해할 수 있을 정도로 거의 아무 일도 일어나지 않습니다.물론 현재 ES6 구문 중 일부는 낯선 것처럼 보일 수 있지만, 이는 ES6가 비교적 새로운 것이기 때문입니다.

이 나타내듯이, 「 」는 「 」입니다.arrayCompare 기능인 '비교 기능'을 있습니다.f및의 입력 어레이, 「2」, 「2」,xs ★★★★★★★★★★★★★★★★★」ysf (x) (y)을 사용법 false의 「」의 .ffalse&&아, 아, 아, 아, 아, 아, 아, 네.따라서 이는 비교기가 초기에 반복을 중지하고 불필요할 때 나머지 입력 배열에서 루프를 방지할 수 있음을 의미합니다.


엄밀한 비교

다음, 우리의 음음, our our를 요.arrayCompare필요한 다른 기능을 쉽게 만들 수 있습니다.초급부터 하겠습니다.arrayEqual

// equal :: a -> a -> Bool
const equal = x => y =>
  x === y // notice: triple equal

// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
  arrayCompare (equal)

const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys))      //=> true
// (1 === 1) && (2 === 2) && (3 === 3)  //=> true

const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs))      //=> false
// (1 === '1')                          //=> false

렇게간간 간간간다다 arrayEqual는 로 할 수 있습니다.arrayCompare 합니다.a로로 합니다.b를 사용합니다.===(이것들)

'아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 이런equal그 자체의 기능인 것처럼요. 해서 이 역할의 중요성을 알 수 .arrayCompare다른 데이터 유형(어레이)의 컨텍스트에서 첫 번째 순서 비교기를 사용하는 고차 함수입니다.


느슨한 비교

할 수 .arrayLooseEqual, 「」의== now . 이제 comparing comparing comparing comparing comparing comparing comparing comparing를 비교할 때1 ~ (번호) ~'1' (String), (String), (String), (String), (String), (String), (String), (String)이 됩니다.true

// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
  x == y // notice: double equal

// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
  arrayCompare (looseEqual)

const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys))    //=> true
// (1 == '1') && (2 == '2') && (3 == '3')  //=> true

상세 비교(재귀적)

당신은 아마 이것이 단지 얄팍한 비교라는 것을 알아차렸을 것이다.분명 Tomash의 솔루션은 암묵적인 깊은 비교를 하기 때문에 "The Right Way™"입니다.

ㅇㅇ, ㅇㅇ는arrayCompare할 수 합니다.

// isArray :: a -> Bool
const isArray =
  Array.isArray

// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
  arrayCompare (a => b =>
    isArray (a) && isArray (b)
      ? arrayDeepCompare (f) (a) (b)
      : f (a) (b))

const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3')         //=> false

console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3')                 //=> true

그렇게 간단하다.또 다른 고차 함수를 사용하여 심층 비교기를 구축합니다.이번에는 저희가 포장하고 있습니다.arrayCompare합니다.a ★★★★★★★★★★★★★★★★★」b 다시 바르세요.arrayDeepCompare 않으면 비교하다a ★★★★★★★★★★★★★★★★★」b(「Comparator에 접속합니다.f이렇게 하면 개별 요소를 실제로 비교하는 방법과는 별도로 상세 비교 동작을 유지할 수 있습니다.ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ,equal,looseEqual 다른 즉 '비교약'입니다

★★★★★★★★★★★★★★★★★★arrayDeepCompare 해서 아까 으로 적용할 수.

// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
  arrayDeepCompare (equal)

// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
  arrayDeepCompare (looseEqual)

필요에 따라 어레이의 얕은 비교 또는 깊은 비교를 명시적으로 선택할 수 있기 때문에 Tomash의 솔루션보다 훨씬 개선된 것입니다.


오브젝트 비교(예)

제제 면면 면면 면면 면면 면면? ' 것 .id여기다

// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
  x.id !== undefined && x.id === y.id

// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
  arrayCompare (idEqual)

const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2)            //=> true

const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6)            //=> false

그렇게 간단하다.여기서는 바닐라 JS 개체를 사용했지만, 이러한 유형의 비교기는 모든 개체 유형에서 사용할 수 있습니다. 사용자 지정 개체에서도 사용할 수 있습니다.이러한 종류의 동등성 테스트를 지원하려면 Tomash의 솔루션을 완전히 수정해야 합니다.

오브젝트와의 깊은 배열문제 없어요.델은 범용성이 높은 범용 기능을 구축했기 때문에 다양한 사용 사례에서 사용할 수 있습니다.

const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys))     //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true

임의 비교(예)

아니면 다른 종류의 완전히 자의적인 비교를 하고 싶다면? 대해 .x보다 y

// gt :: Number -> Number -> Bool
const gt = x => y =>
  x > y

// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)

const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys))     //=> true
// (5 > 2) && (10 > 4) && (20 > 8)  //=> true

const zs = [6,12,24]
console.log (arrayGt (xs) (zs))     //=> false
// (5 > 6)                          //=> false

적은 것이 많은 것

보다 적은 코드로 더 많은 것을 할 수 있습니다.할 것 없다arrayCompare그 자체와 우리가 만든 각각의 커스텀 컴퍼레이터에는 매우 간단한 구현이 있습니다.

의 절차로 얕은 어레이, 깊은 어레이, 엄격한 어레이, 느슨한 어레이, 오브젝트 속성 또는 임의의 계산 또는 이들 조합의 2가지 어레이를 비교하는 방법을 쉽게 정의할 수 있습니다.arrayCompare도 꿀 수 도 몰라RegExp이 그!

가장 빠른가요?아뇨, 하지만 그럴 필요도 없을 거예요코드의 품질을 측정하기 위해서 속도가 유일한 지표라면, 많은 훌륭한 코드가 폐기될 것입니다.이 때문에, 저는 이 어프로치를 「실용적인 방법」이라고 부릅니다.아니면 좀 더 공정하게 실용적인 방법일 수도 있어요.이 설명은 이 답변에 적합하다.왜냐하면 이 답변이 다른 답변에 비해 실용적이라고 말하는 것이 아니라 객관적으로 사실이다.우리는 매우 쉽게 추론할 수 있는 아주 작은 코드로 높은 수준의 실용성을 실현했습니다.다른 어떤 코드도 우리가 이 설명을 얻지 못했다고 말할 수 없습니다.

이것이 당신에게 "적절한" 솔루션이 됩니까?그건 당신이 결정할 일이에요.그리고 아무도 당신을 위해 그것을 할 수 없습니다. 오직 당신만이 당신이 무엇을 원하는지 알고 있습니다.대부분의 경우, 저는 똑똑하고 빠른 종류보다 간단하고 실용적이며 다재다능한 코드를 중시합니다.가치관이 다를 수 있으니 자신에게 맞는 것을 고르세요.


편집

에 더 을 맞췄습니다.arrayEqual아주 작은 절차로요.이것은 흥미로운 연습이지만, 이 문제에 접근하는 가장 좋은 방법은 아닙니다.관심 있는 경우 이 개정 내역을 볼 수 있습니다.

"동일하다"는 말이 무슨 뜻인지 잘 모르겠어요.를 들어,는 「」입니다.a ★★★★★★★★★★★★★★★★★」b(네스트된 어레이에 주목해 주세요)는 다음과 같습니다.

var a = ["foo", ["bar"]], b = ["foo", ["bar"]];

각 줍니다.즉, 에서는, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」, 「 」와 같이 됩니다.arraysIdentical(a, b)false JSON-의 경우에 join()- 기능이 없습니다 반반-기반 、 - - - - 。

function arraysIdentical(a, b) {
    var i = a.length;
    if (i != b.length) return false;
    while (i--) {
        if (a[i] !== b[i]) return false;
    }
    return true;
};

Tomash Zato의 답변을 바탕으로 어레이를 통해 반복하는 것이 가장 빠르다는 데 동의합니다.또한 (다른 사람들이 이미 언급한 것과 마찬가지로) 함수는 비교가 아니라 동등/동일함수라고 불러야 합니다.이 점을 고려하여 유사성을 위해 어레이를 비교하기 위해 기능을 변경했습니다.즉, 어레이는 같은 요소를 가지고 있지만, 순서가 어긋나 있습니다.개인적인 용도로 사용할 수 있도록 여기에 던져서 모든 사람이 볼 수 있도록 했습니다.

Array.prototype.equals = function (array, strict) {
    if (!array)
        return false;

    if (arguments.length == 1)
        strict = true;

    if (this.length != array.length)
        return false;

    for (var i = 0; i < this.length; i++) {
        if (this[i] instanceof Array && array[i] instanceof Array) {
            if (!this[i].equals(array[i], strict))
                return false;
        }
        else if (strict && this[i] != array[i]) {
            return false;
        }
        else if (!strict) {
            return this.sort().equals(array.sort(), true);
        }
    }
    return true;
}

이 함수는 기본적으로 true로 설정된 strict라는 추가 파라미터를 사용합니다.이 엄밀한 파라미터는 배열이 콘텐츠와 그 콘텐츠의 순서 모두 완전히 동일해야 하는지, 아니면 단순히 동일한 콘텐츠만 포함해야 하는지를 정의합니다.

예제:

var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 4, 3];  // Loosely equal to 1
var arr3 = [2, 2, 3, 4];  // Not equal to 1
var arr4 = [1, 2, 3, 4];  // Strictly equal to 1

arr1.equals(arr2);         // false
arr1.equals(arr2, false);  // true
arr1.equals(arr3);         // false
arr1.equals(arr3, false);  // false
arr1.equals(arr4);         // true
arr1.equals(arr4, false);  // true

jsfiddle을 사용하다
http://jsfiddle.net/Roundaround/DLkxX/httpjsfiddle.net//DLkxX/

JSON.encode와 같은 행에 join()을 사용합니다.

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    //slice so we do not effect the original
    //sort makes sure they are in order
    //join makes it a string so we can do a string compare
    var cA = arrA.slice().sort().join(","); 
    var cB = arrB.slice().sort().join(",");

    return cA===cB;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];  //will return true

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //true

유일한 문제는 지난번 비교에서 테스트한 유형을 신경 쓰는 경우입니다.타입에 관심이 있는 경우는, 루프 할 필요가 있습니다.

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;

    //slice so we do not effect the orginal
    //sort makes sure they are in order
    var cA = arrA.slice().sort(); 
    var cB = arrB.slice().sort();

    for(var i=0;i<cA.length;i++){
         if(cA[i]!==cB[i]) return false;
    }

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,b) );  //true
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false

순서가 단순한 루프가 아닌 동일한 상태로 유지되는 경우 정렬은 필요하지 않습니다.

function checkArrays( arrA, arrB ){

    //check if lengths are different
    if(arrA.length !== arrB.length) return false;


    for(var i=0;i<arrA.length;i++){
         if(arrA[i]!==arrB[i]) return false;
    }

    return true;

}

var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];

console.log( checkArrays(a,a) );  //true
console.log( checkArrays(a,b) );  //false
console.log( checkArrays(a,c) );  //false
console.log( checkArrays(a,d) );  //false
console.log( checkArrays(a,e) );  //false

비교한 어레이에는 숫자와 문자열만 포함되어 있습니다.이 함수는 배열에 동일한 요소가 포함되어 있는지 여부를 표시합니다.

function are_arrs_match(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_match(arr1, arr2)) //true
console.log (are_arrs_match(arr1, arr3)) //false

많은 해답을 가지고 있지만, 도움이 될 것 같은 해답이 있습니다.

const newArray = [ ...new Set( [...arr1, ...arr2] ) ]

어레이의 구조가 어떻게 되어 있는지에 대해서는 질문에는 기재되어 있지 않습니다.따라서 어레이에 네스트된 어레이나 오브젝트가 없는 것을 확실히 알고 있는 경우(이 때문에 이 답변을 하게 되었습니다).

이 경우 분산 연산자(...)를 사용하여 두 어레이를 연결한 후 Set을 사용하여 중복을 제거합니다.사이즈를 비교한 후, 3개의 어레이가 모두 같은 사이즈를 가지고 있는 경우는, 즉시 사용할 수 있습니다.

이 답변은 요소의 순서도 무시하고 있습니다.제가 말씀드린 것처럼 정확한 상황이 일어났기 때문에 같은 상황에 있는 사람이 (저와 같은) 이곳에 오게 될지도 모릅니다.


편집1.

Dmitry Grinko의 질문에 대한 답변: "왜 여기서 스프레드 연산자(...)를 사용했습니까 - ...new Set ? 작동하지 않습니다."

다음 코드를 고려하십시오.

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

얻을 수 있을 것이다

[ Set { 'a', 'b', 'c' } ]

이 값을 사용하려면 몇 가지 Set 속성을 사용해야 합니다(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) 참조).한편, 이 코드를 사용하는 경우:

const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ ...new Set( [...arr1, ...arr2] ) ]
console.log(newArray)

얻을 수 있을 것이다

[ 'a', 'b', 'c' ]

이것이 차이점입니다. 전자는 저에게 세트를 제공합니다.그 세트의 사이즈를 얻을 수 있는 만큼 동작합니다만, 후자는 필요한 어레이를 제공합니다.해상도에는 보다 직접적인 것이 있습니다.

최단

일련의 번호의 경우는, 다음의 조작을 실시합니다.

a1==''+a2

var a1 = [1,2,3];
var a2 = [1,2,3];

console.log( a1==''+a2 )

주의: 어레이에 문자열이 포함되어 있는 경우, 이 메서드는 동작하지 않습니다.a2 = [1, "2,3"].

lodash 라이브러리에서 isEqual을 간단히 사용할 수 있습니다.그것은 매우 효율적이고 깨끗하다.

import isEqual from "lodash/isEqual";

const isTwoArraysEqual = isEqual(array1, array2);

두 어레이의 요소가 동일하지만 순서가 다른 경우에는 코드가 문제를 적절하게 처리하지 못합니다.

제 코드를 당신의 예와 비교해 보십시오.이 예에서는 요소가 숫자인 두 배열을 다른 요소 유형으로 수정하거나 확장할 수 있습니다(.toString() 대신 .join()을 사용합니다).

var a1 = [1,2,3];
var a2 = [1,2,3];
const arraysAreEqual = a1.sort().toString()==a2.sort().toString();
// true if both arrays have same elements else false
console.log(arraysAreEqual);

코드 골프

어레이를 효율적으로 비교하는 방법을 나타내는 답변은 많이 있습니다.

다음은 코드 바이트 단위로 측정되는2개의 int 또는 (string) 어레이를 비교하는 가장 짧은 방법입니다.

const a = [1, 2, 3]
const b = [1, 2, 3]

console.log("1. ", a.join() == b.join())
console.log("2. ", a.join() == [].join())

console.log("3. ", 1 + a == 1 + b)
console.log("4. ", 1 + [] == 1 + b)

// even shorter
console.log("4. b) ", a == "" + b)

// false positives (see flaws)
console.log("5. ", 1 + ["3"] == 1 + [3]) // type differences
console.log("6. ", 1 + ["1,2"] == 1 + ["1", "2"])

설명.

동작은, 「 」, 「 」를 ,+연산자, 유형이 자동으로 변환되어 연결이 허용됩니다. 「」는,1[1, 2, 3]을 하다

는 "JavaScript"를 사용합니다.[1, 2, 3].join()11,2,3에서 이 '어레이'를 사용할 수 === ★★★★★★★★★★★★★★★★★」==두 줄을 비교합니다.

결함

이 기술을 사용하면 비교할 배열의 요소가 서로 다른 유형이어도 상관없습니다. [1, 2] 되다["1", "2"]문자열 변환 때문입니다.

된 바와 배열을 하면 다음과 할 수 .["1,2"]에 '적합'하다["1", "2"]이런 일이 일어나지 않는다고 확신하는 경우(예를 들어 많은 코드 골프 경기)에는 문제가 되지 않습니다.

부인

코드 골프에서는 유용하지만 실제 코드에서는 사용하지 않는 것이 좋습니다.지적된 두 가지 결점도 도움이 되지 않습니다.

여기에는 복잡한 긴 답변이 많이 있습니다. 따라서 간단한 답변 하나만 드리겠습니다. 바로 toString()을 사용하여 어레이를 ===과 쉽게 비교할 수 있는 단순한 쉼표로 구분된 문자열로 변환합니다.

let a = [1, 2, 3]
let b = [1, 2, 3]
let c = [4, 2, 3]

console.log(a.toString())  // this outputs "1,2,3"
console.log(a.toString() === b.toString())  // this outputs true because "1,2,3" === "1,2,3"
console.log(a.toString() === c.toString())  // this outputs false because "1,2,3" != "4,2,3"

다음은 Typescript 버전입니다.

//https://stackoverflow.com/a/16436975/2589276
export function arraysEqual<T>(a: Array<T>, b: Array<T>): boolean {
    if (a === b) return true
    if (a == null || b == null) return false
    if (a.length != b.length) return false

    for (var i = 0; i < a.length; ++i) {
        if (a[i] !== b[i]) return false
    }
    return true
}

//https://stackoverflow.com/a/16436975/2589276
export function arraysDeepEqual<T>(a: Array<T>, b: Array<T>): boolean {
    return JSON.stringify(a) === JSON.stringify(b)
}

mocha 테스트 케이스:

it('arraysEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']

    expect(arraysEqual(a, b)).to.equal(true)
    expect(arraysEqual(c, d)).to.equal(true)
    expect(arraysEqual(a, d)).to.equal(false)
    expect(arraysEqual(e, f)).to.equal(true)
    expect(arraysEqual(f, g)).to.equal(false)
})

it('arraysDeepEqual', function () {
    let a = [1,2]
    let b = [1,2]
    let c = [2,3]
    let d = [2, 3]
    let e = ['car','apple','banana']
    let f = ['car','apple','banana']
    let g = ['car','apple','banan8']
    let h = [[1,2],'apple','banan8']
    let i = [[1,2],'apple','banan8']
    let j = [[1,3],'apple','banan8']

    expect(arraysDeepEqual(a, b)).to.equal(true)
    expect(arraysDeepEqual(c, d)).to.equal(true)
    expect(arraysDeepEqual(a, d)).to.equal(false)
    expect(arraysDeepEqual(e, f)).to.equal(true)
    expect(arraysDeepEqual(f, g)).to.equal(false)
    expect(arraysDeepEqual(h, i)).to.equal(true)
    expect(arraysDeepEqual(h, j)).to.equal(false)
})

2020년에 도입된 1단계 제안이 있습니다. 이를 통해 어레이를 쉽게 비교할 수 있습니다.Array.prototype.equals라이브러리, 몽키패칭, 기타 코드 없이 다음과 같이 동작합니다.

[1, 2, 3].equals([1, 2, 3]) // evaluates to true
[1, 2, undefined].equals([1, 2, 3]) // evaluates to false
[1, [2, [3, 4]]].equals([1, [2, [3, 4]]]) // evaluates to true

TC39는 이제 "문제 공간, 솔루션 및 교차 우려 사항을 검토하는 데 시간을 할애할 것"이라는 잠정적인 제안에 불과합니다.만약 그것이 2단계에 진입한다면, 그것은 결국 적절한 언어로 통합될 가능성이 높다.

Mocha와 같은 테스트 프레임워크를 Chai 어설션 라이브러리와 함께 사용하는 경우 딥 이퀄리티를 사용하여 어레이를 비교할 수 있습니다.

expect(a1).to.deep.equal(a2)

이 값은 배열이 대응하는 인덱스에서 동일한 요소를 가지고 있는 경우에만 true를 반환합니다.

숫자 또는 문자열의 2개의 배열만 있는 경우, 이것은 한 줄의 짧은 배열입니다.

const array1 = [1, 2, 3];
const array2 = [1, 3, 4];
console.log(array1.join(',') === array2.join(',')) //false

const array3 = [1, 2, 3];
const array4 = [1, 2, 3];
console.log(array3.join(',') === array4.join(',')) //true

여기 있어요.

const a = [1, 2, 3]
const b = [1, 2, 3, 4, 5]

const diff = b.filter(e => !a.includes(e))
console.log(diff)

위의 답변의 대부분은 순서 없는 목록에는 적용되지 않습니다.이것은 순서 없는 리스트에서도 유효합니다.

const a = [3, 2, 1]
const b = [1, 2, 3, 4, 5]

const diff = b.filter(e => !a.includes(e))
console.log(diff)

a의 크기가 b보다 클 경우

const a = [1, 2, 3, 4, 5]
const b = [3, 2, 1]

const diff = a.length > b.length ? a.filter(e => !b.includes(e)) : b.filter(e => !a.includes(e))
console.log(diff)

코드 수가 매우 적은 또 다른 접근법(어레이 리덕션 및 어레이 사용)은 다음과 같습니다.

arr1.length == arr2.length && arr1.reduce((a, b) => a && arr2.includes(b), true)

순서 동일성도 비교하려면:

arr1.length == arr2.length && arr1.reduce((a, b, i) => a && arr2[i], true)
  • length한 배열의 요소 집합이 다른 배열의 하위 집합이 아님을 확인합니다.

  • 리듀서는 하나의 어레이를 통과하여 다른 어레이의 각 항목을 검색하는 데 사용됩니다.수 없는 는 반환됩니다.false

    1. 첫 번째 예에서는 요소가 포함된 것을 테스트하고 있습니다.
    2. 두 번째 예에서도 주문을 확인합니다.

좋은 답변들이 많네요.이게 제가 평소에 하는 방식이에요.

if ( arr1.length === arr2.length && arr1.every((a1) => arr2.includes(a1)) ) {
   // logic
}

every()모든 요소가 지정된 캄파리슨 로직을 통과할 경우에만 true를 반환합니다.거짓

시간의 복잡도는 O(n*m)가 됩니다.

사용할 수 .every(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/every)

function compareArrays(array1, array2) {
    if (array1.length === array2.length)
        return array1.every((a, index) => a === array2[index])
    else
        return false
}

// test
var a1 = [1,2,3];
var a2 = [1,2,3];

var a3 = ['a', 'r', 'r', 'a', 'y', '1']
var a4 = ['a', 'r', 'r', 'a', 'y', '2']

console.log(compareArrays(a1,a2)) // true
console.log(compareArrays(a1,a3)) // false
console.log(compareArrays(a3,a4)) // false

여기서는 2개의 정렬되지 않은 어레이를 비교합니다.

function areEqual(a, b) {
  if ( a.length != b.length) {
    return false;
  }
  return a.filter(function(i) {
    return !b.includes(i);
  }).length === 0;  
}

간단한 접근법:

function equals(a, b) {
    if ((a && !b) || (!a && b) || (!a && !b) || (a.length !== b.length)) {
        return false;
    }

    var isDifferent = a.some(function (element, index) { 
        return element !== b[index];
    });

    return !isDifferent;
}

여기에 정렬되지 않은 어레이와 커스텀 비교가 있을 수 있습니다.

    const array1 = [1,3,2,4,5];
    const array2 = [1,3,2,4,5];
    
    const isInArray1 = array1.every(item => array2.find(item2 => item===item2))
    const isInArray2 = array2.every(item => array1.find(item2 => item===item2))
    
    const isSameArray = array1.length === array2.length && isInArray1 && isInArray2
    
    console.log(isSameArray); //true

제 해결책은 다음과 같습니다.

/**
 * Tests two data structures for equality
 * @param {object} x
 * @param {object} y
 * @returns {boolean}
 */
var equal = function(x, y) {
    if (typeof x !== typeof y) return false;
    if (x instanceof Array && y instanceof Array && x.length !== y.length) return false;
    if (typeof x === 'object') {
        for (var p in x) if (x.hasOwnProperty(p)) {
            if (typeof x[p] === 'function' && typeof y[p] === 'function') continue;
            if (x[p] instanceof Array && y[p] instanceof Array && x[p].length !== y[p].length) return false;
            if (typeof x[p] !== typeof y[p]) return false;
            if (typeof x[p] === 'object' && typeof y[p] === 'object') { if (!equal(x[p], y[p])) return false; } else
            if (x[p] !== y[p]) return false;
        }
    } else return x === y;
    return true;
};

중첩된 데이터 구조에서 작동하며 개체의 메서드를 무시합니다.이 방법으로 Object.protype을 확장할 생각은 하지 마십시오.한 번 시도했을 때 jQuery가 고장났습니다.

대부분의 어레이에서는 여전히 대부분의 시리얼라이제이션 솔루션보다 고속입니다.객체 레코드 배열에 대한 가장 빠른 비교 방법일 것입니다.

JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ?  array.push(collection[i]) : null

이렇게 했어요.

이미 훌륭한 답변들이 있습니다.그러나 어레이 비교에서 신뢰성이 입증된 다른 아이디어를 공유하고자 합니다.JSON.stringize ()를 사용하여2개의 어레이를 비교할 수 있습니다.이것에 의해, 어레이로부터 스트링이 작성되어 2개의 어레이로부터 취득한2개의 스트링이 동등하게 비교됩니다.

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:1},2]) //true

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},2]) //false

JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:1},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //false

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //true

JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[4]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false

JSON.stringify([1,{a:2},[3,4,[5]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //true

언급URL : https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript

반응형