두 배열의 값이 동일한 지 확인하는 방법


104

이 두 배열이 있습니다. 하나는 ajax 요청의 정보로 채워지고 다른 하나는 사용자가 클릭하는 버튼을 저장합니다. 이 코드를 사용합니다 (샘플 번호로 채웠습니다).

var array1 = [2, 4];
var array2 = [4, 2]; //It cames from the user button clicks, so it might be disordered.
array1.sort(); //Sorts both Ajax and user info.
array2.sort();
if (array1==array2) {
    doSomething();
}else{
    doAnotherThing();
}

그러나 false두 배열이 동일하지만 이름이 다른 경우에도 항상을 제공합니다 . (Chrome의 JS 콘솔에서 확인했습니다). 그래서,이 두 배열이 같은 것을 포함하는지 알 수있는 방법이 있습니까? 왜 주는가 false? 첫 번째 배열의 어떤 값이 두 번째 배열에 없는지 어떻게 알 수 있습니까?


1
배열의 각 요소를 살펴볼 필요가 있다고 확신합니다.
Thomas Li

왜 거짓을 반환하는지 아십니까? 궁금한.
RobW


답변:


36
function arraysEqual(_arr1, _arr2) {

    if (!Array.isArray(_arr1) || ! Array.isArray(_arr2) || _arr1.length !== _arr2.length)
      return false;

    var arr1 = _arr1.concat().sort();
    var arr2 = _arr2.concat().sort();

    for (var i = 0; i < arr1.length; i++) {

        if (arr1[i] !== arr2[i])
            return false;

    }

    return true;

}

이것은 이전 답변과 달리 원래 배열을 수정하지 않습니다.


2
정렬에는 nlog (n) 시간이 걸립니다. 정렬 할 필요가 없습니다. 이 답변은 stackoverflow.com/a/55614659/3209523 이 선형 시간으로 작동합니다.
canbax

typescript를 사용하면 Array.isArray ()에서 오류가 발생하여 제대로 작동하는지 제거했습니다.
Ariel Frischer

89

배열 항목이 객체가 아닌 경우 (예 : 숫자 또는 문자열 인 경우) 결합 된 문자열을 비교하여 순서에 상관없이 동일한 멤버가 있는지 확인할 수 있습니다.

var array1= [10, 6, 19, 16, 14, 15, 2, 9, 5, 3, 4, 13, 8, 7, 1, 12, 18, 11, 20, 17];
var array2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];

if(array1.sort().join(',')=== array2.sort().join(',')){
    alert('same members');
}
else alert('not a match');

2
이것은 toString 값을 고유하게 식별하는 기본 체 또는 객체에 대해 잘 작동하지만 모든 객체에는 적합하지 않습니다.
devios1

감사! 깔끔한 솔루션
Gaston Sanchez

3
null 항목 및 정렬에주의하십시오. 필자의 경우에는 ", 2,2,3"과 "2,2,3"과 같이 비교하는 문자열을 사용했는데, 이는 물론 완전히 같지는 않습니다.
barbara.post 2015

2
문자열, 즉 ['a', 'b']['a,b']. 이 기술은 작은 일회용 스크립트에만 권장됩니다.
알렉스

1
@alex-제 경우에는 문자열에 쉼표가 허용되지만 세미콜론은 허용되지 않으므로 ';'를 사용했습니다. 쉼표 대신 가입
a2345sooted

45

두 배열이 동일한 값 (각 값의 발생 횟수 및 순서에 관계없이)을 갖는 경우에만 확인하려면 lodash 를 사용하여 수행 할 수 있습니다 .

_.isEmpty(_.xor(array1, array2))

짧고 간단하고 예쁘다!


1
xor밑줄 문서에서 찾을 수없는 것 같습니까? IODash를 생각하고 있습니까?
Patrick Mencias-lewis 2015

44
Array.prototype.compare = function(testArr) {
    if (this.length != testArr.length) return false;
    for (var i = 0; i < testArr.length; i++) {
        if (this[i].compare) { //To test values in nested arrays
            if (!this[i].compare(testArr[i])) return false;
        }
        else if (this[i] !== testArr[i]) return false;
    }
    return true;
}

var array1 = [2, 4];
var array2 = [4, 2];
if(array1.sort().compare(array2.sort())) {
    doSomething();
} else {
    doAnotherThing();
}

아마도?


감사합니다! 원하는대로 작동합니다. 나는 또한 얼마나 많은 불일치가 있는지 알 수 있도록 기능을 약간 수정했습니다.
Carlos Precioso 2011 년

[2,4] [4,2]에 대해 거짓입니다.
Suraz Khanal

여전히 일종의 필요 @SurazKhanal
아론 McMillin에게

26

코드가 작동하지 않는 이유

JavaScript에는 원시 데이터 유형 과 비 원시 데이터 유형이 있습니다.

기본 데이터 타입의 경우 =====체크 바의 양쪽에있는 것들과 동일한 값을 가져야하는지 여부. 그것이 1 === 1사실입니다.

배열 ==과 같은 원시 데이터 유형이 아닌 ===경우 참조 동등성을 확인하십시오. 즉 그들은 여부를 확인한다 arr1arr2같은 객체입니다. 귀하의 예에서 두 배열은 동일한 순서로 동일한 객체를 갖지만 동일하지는 않습니다.

솔루션

두 배열 arr1arr2은 다음과 같은 경우에만 동일한 멤버를 갖습니다.

  • 모든 것이 들어 arr2있습니다.arr1

  • 모든 것이 들어 arr1있습니다.arr2

그래서 이것은 트릭을 할 것입니다 (ES2016) :

const containsAll = (arr1, arr2) => 
                arr2.every(arr2Item => arr1.includes(arr2Item))

const sameMembers = (arr1, arr2) => 
                        containsAll(arr1, arr2) && containsAll(arr2, arr1);

sameMembers(arr1, arr2); // `true`

Underscore를 사용하는이 두 번째 솔루션 은 수행하려는 작업에 더 가깝습니다.

arr1.sort();
arr2.sort();

_.isEqual(arr1, arr2); // `true`

isEqual"깊은 평등"을 확인하기 때문에 작동 합니다. 즉, 참조 평등 이상을보고 값을 비교합니다.

세 번째 질문에 대한 해결책

또한에 arr1포함되지 않은 항목을 찾는 방법을 물었 습니다 arr2.

이렇게하면됩니다 (ES2015).

const arr1 = [1, 2, 3, 4];
const arr2 = [3, 2, 1];

arr1.filter(arr1Item => !arr2.includes(arr1Item)); // `[4]`

Underscore의 difference: 메소드를 사용할 수도 있습니다 .

_.difference(arr1, arr2); // `[4]`

최신 정보

@Redu의 의견을 참조하십시오. 내 솔루션은에 대한 sameMembers것이지만 염두에 두어야 할 것은으로 sameMembersInOrder도 알려져 있습니다 deepEquals.

업데이트 2

배열 멤버의 순서에 신경 쓰지 않는다면 ES2015 + SetArray. 위험한 원숭이 패치 를 구현 isSuperset하고difference 사용 하는 방법에 대한 MDN 노트를 참조하십시오 .


1
귀하의 솔루션이 잘못되었습니다. "두 배열, arr1 및 arr2는 다음과 같은 경우에만 동일한 구성원을 갖습니다. arr2의 모든 것이 arr1에 있고 arr1의 모든 것이 arr2에 있습니다."이것은 또한 잘못된 것입니다. 이것은 집합이 아닌 배열입니다. 따라서 sameMembers([1,1,2],[2,1,2]);false를 반환해야합니다.
Redu

1
@Redu는 "동일한 구성원"이 무엇을 의미하는지에 따라 달라집니다. "동일한 구성원이 있음"을 의미합니다. 내 의견으로는을 sameMembers([1,1,2],[2,1,2])반환해야합니다 true. sameMembersInOrder([1,1,2],[2,1,2])AKA deepEquals([1,1,2],[2,1,2])가 반환해야합니다 false.
Max Heiber

세 번째 솔루션 arr1.filter...은 arr2에 arr1의 모든 요소가 있는지 여부를 확인하는 데만 작동하지만 그 반대의 경우도 필요합니다.
Aakash Verma

10

객체 동등성 검사 :JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())

위의 테스트는 http://www.w3schools.com/jsref/jsref_sort.asp에 설명 된대로 정렬 기능을 사용하는 경우 객체 배열에서도 작동합니다 .

플랫 JSON 스키마가있는 작은 배열에 충분할 수 있습니다.


9

우리의 목표는 기본적으로 2 개의 배열이 동일한 집합인지 확인하는 것입니다. 집합 은 수학적으로 정의 된 집합 입니다. 가장 빠른 정렬은 점근 적으로 O (nlog (n)) 시간이 걸립니다. 따라서 배열을 정렬하면 최소한 O (nlog (n)) 시간이 걸립니다. 그러나이 작업을 더 빠르게 수행 있으며, 사전 데이터 구조에서 점근 적으로 O (n) 시간 (최악의 경우가 아닌 평균 사례 ) 이 걸립니다 . JS에서 사전은 단순히 키와 값이있는 객체입니다.

/** assumes array elements are primitive types
* check whether 2 arrays are equal sets.
* @param  {} a1 is an array
* @param  {} a2 is an array
*/
function areArraysEqualSets(a1, a2) {
  const superSet = {};
  for (const i of a1) {
    const e = i + typeof i;
    superSet[e] = 1;
  }

  for (const i of a2) {
    const e = i + typeof i;
    if (!superSet[e]) {
      return false;
    }
    superSet[e] = 2;
  }

  for (let e in superSet) {
    if (superSet[e] === 1) {
      return false;
    }
  }

  return true;
}

이 기능은 원시 형의 배열로 작동하고 가정합니다 a1a2배열입니다.


5

이건 어때? ES 2017 내 생각 :

const array1 = [1, 3, 5];
const array2 = [1, 5, 3];

const isEqual = (array1.length === array2.length) && (array1.every(val => array2.includes(val)));
console.log(isEqual);

첫 번째 조건은 두 배열의 길이가 동일한 지 확인하고 두 번째 조건은 첫 번째 배열이 두 번째 배열의 하위 집합인지 확인합니다. 이 두 조건을 결합하면 요소 순서에 관계없이 두 배열의 모든 항목을 비교해야합니다.

위 코드는 두 배열에 중복되지 않는 항목이있는 경우에만 작동합니다.


3

이 두 배열을 비교할 때 내용이 아니라 배열을 나타내는 객체를 비교하는 것입니다.

둘을 비교하려면 함수를 사용해야합니다. 길이가 동일한 지 확인한 후 단순히 하나를 반복하고 다른 것과 비교하는 자신을 작성할 수 있습니다.


3

ES6를 사용한 얕은 평등을위한 간단한 솔루션 :

const arr1test = arr1.slice().sort()
const arr2test = arr2.slice().sort()
const equal = !arr1test.some((val, idx) => val !== arr2test[idx])

각 배열의 얕은 복사본을 만들고 정렬합니다. 그런 다음을 사용 some()하여 arr1test값 을 반복 arr2test하여 동일한 인덱스 의 값 과 비교하여 각 값을 확인합니다 . 모든 값이 같으면을 some()반환 false하고로 equal평가됩니다 true.

를 사용할 수도 every()있지만 true결과 를 만족시키기 위해 배열의 모든 요소를 ​​순환해야하는 반면 some()같지 않은 값을 찾으면 즉시 보석이됩니다.

const equal = arr1test.every((val, idx) => val === arr2test[idx])

2

게임 프로젝트에서 간단한 정수 값을
가졌습니다. 각 배열의 값 수가 적었고 원래 배열이 손대지 않은 상태로 필요했습니다.
그래서 아래 작업을 수행했는데 제대로 작동했습니다. (여기에 붙여 넣기 위해 편집 된 코드)

var sourceArray = [1, 2, 3];
var targetArray = [3, 2, 1];

if (sourceArray.length !== targetArray.length) {
    // not equal
    // did something
    return false;
}

var newSortedSourceArray = sourceArray.slice().sort();
var newSortedTargetArray = targetArray.slice().sort();

if (newSortedSourceArray.toString() !== newSortedTargetArray.toString()) { // MAIN CHECK
    // not equal
    // did something
    return false;
}
else {
    // equal
    // did something
    // continued further below
}

// did some more work

return true;

도움이 되었기를 바랍니다.


2

ES6 사용

Ramda의 equals함수를 사용하지만 대신 Lodash 또는 Underscore를 사용할 수 있습니다 isEqual.

const R = require('ramda');

const arraysHaveSameValues = (arr1, arr2) => R.equals( [...arr1].sort(), [...arr2].sort() )

Spread opporator를 사용하여 원래 배열의 변형을 피하고 함수를 순수하게 유지합니다.


2

reduce루프 대신 사용 하여 영리하게 보일 수 있지만 동료 개발자가 당신을 똑똑한 바보로 생각하게 할 위험이 있습니다.

function isArrayContentSame(a, b) {
  if (Array.isArray(a) && Array.isArray(b) && a.length == b.length) {
    a = a.concat().sort()
    b = b.concat().sort()
    return a.reduce((acc,e,i) => acc && e === b[i], true)
  } else {
    return false;
  }
}

1

배열의 항목이 원시 (숫자 또는 단일 문자) 인 경우 길이 비교 및 ​​세트 사용의 조합을 사용할 수 있습니다.

function equalArrayItems(arr1, arr2) {
  if (arr1.length !== arr2.length) return false
  const set1 = new Set(arr1)
  const set2 = new Set(arr2)
  const set3 = new Set(arr1, arr2)
  return set1.size === set3.size && set2.size === set3.size
}

1

이미 2020 년이지만 대부분의 다른 솔루션은 정렬, O (n * log n), 라이브러리 사용 또는 O (n ^ 2) 복잡성을 사용합니다.

다음은 선형 복잡성 O (n)을 가진 순수한 Javascript 솔루션입니다.

/**
 * Check if two arrays of strings or numbers have the same values regardless of the order
 * @param {string[]|number[]} arr1
 * @param {string[]|number[]} arr2
 * @return {boolean}
 */    
compareArrays = (arr1, arr2) => {
    if (arr1.length !== arr2.length) return false;
    const lk1 = {};
    const lk2 = {};
    let i = arr1.length;
    while (--i >= 0) {
        lk1[arr1[i]] = true;
        lk2[arr2[i]] = true
    }
    i = arr1.length;
    while (--i >= 0) {
        const v = arr1[i];
        if (lk1[v] !== lk2[v]) return false;
    }
    return true
}

테스트 :

compareArrays([2, 4], [4, 2]) => true
compareArrays([2, 4], [4, 2, 7]) => false
compareArrays([], []) => true

1
이봐, 멋진 항목이야! 상당히 복잡하지만 의미가 있습니다. 질문이 있습니다. Big O 표기법에 익숙하지 않지만 확실히이 알고리즘은 O (2n)입니까? 하지만 그것이 큰 차이를 만든다고 생각하지 마십시오.
Carlos Precioso

1
@CarlosPrecioso 맞습니다. O (2n) = O (n). 복잡도는 상수 계수를
SC1000

0

Prototype Framework를 사용하는 경우 배열 의 intersect 메서드를 사용 하여 순서에 관계없이 동일한 지 확인할 수 있습니다.

var array1 = [1,2];
var array2 = [2,1];

if(array1.intersect(array2).length === array1.length) {
    alert("arrays are the same!");
}

작동하지 않습니다-true를 [1,2].intersect([1,2,3]).length === [1,2].length반환합니다. 원본 배열의 길이도 비교해야합니다. 설명하기 위해 게시물을 편집했습니다.
GMA

사실 중복의 경우 제안 된 편집이 작동하지 않는다는 것을 방금 깨달았습니다. 예를 들어 false를 반환합니다 array1 = [1,1,2]; array2 = [1,1,2];... 원래 답변은 해당 입력에 대해 실패하지 않습니다.
GMA

당신과 반대의 작업을 수행 할 수 있습니다_.difference(array1, array2).length;

0

이 답변을 친절하게 확인하십시오.

var arr1= [12,18];
var arr2= [12, 18, 20, 11, 19, 14, 6, 7, 8, 16, 9, 3, 1, 13, 5, 4, 15, 10, 2, 17];
for(i=0;i<arr1.length;i++)
{
var array1=arr1[i];
for(j=0;j<arr2.length;j++)
{
    var array2=arr2[j];
    if(array1==array2)
    {
return true;
    }
}
}

2
이것은 몇 가지 오류를 제외 하고는이 답변 과 기능적으로 동일 합니다. 첫째, 이것은 모두 함수 내에서 래핑되어야합니다. 그렇지 return않으면 효과가 없습니다. 둘째, 당신은, 정렬 된 배열을 확인해야 [1,2]하고 [2,1]동일하지로 감지됩니다. 세 번째이자 가장 중요한 것은 실제로 일부 요소 가 동일한 지 확인하는 것 입니다. 조건부는이어야합니다 if (array1!==array2) {return false;}. 아마도 이것은 미래에 당신을 도울 수 있습니다!
Carlos Precioso

1
추가 설명으로 코드 흐름을 더 잘 이해하고 변수 이름을 더 명확하게하기 위해 들여 쓰기를 사용하십시오. 예를 들면 : array1array2이름을 바꿀 수 elem1elem2. 이 두 가지 팁은 앞으로 많은 두통을 덜어 줄 것입니다!
Carlos Precioso

2
추가 검사에서 왜 이중 루프입니까? 두 배열은 길이가 같아야하며 그렇지 않은 경우 직접적으로 동일하지 않습니다. 이렇게하면 하나의 루프 만 사용할 수 있습니다. 지금,이 코드를 검사하는 경우 어느 첫 번째 배열의 요소는 어디서든 제 일인치 이 답변 을 확인 하여 구현 방법을 확인하십시오. JavaScript 여행에서 행운을 빕니다!
Carlos Precioso

0

오랜 시간이 지났지 만 이것이 간단한 해결책과 현대적인 초보자를 찾는 사람에게 도움이되기를 바랍니다.

이제 우리는 이런 식 사용하여 여러 라이브러리를 달성 할 수있다 lodash, underscore등 (이 때문에 단순 여러 기능과 높은 사용에 현재 프로젝트의 일부가됩니다)

lodash 라이브러리에서 교차점을 사용할 수 있습니다.

_.intersection(['2-1', '1'], ['2-2', '3-1', '2-1']); 
// => ['2-1']

이것은 모든 데이터 유형에 대해 작동합니다 ..


0

두 배열을 비교하고 두 배열에서 동일한 객체가 있는지 확인하려면 작동합니다. 예 :

배열 1 = [a, b, c, d]
배열 2 = [d, e, f, g]

여기서 'd'는 두 배열 모두에서 공통이므로이 함수는 참 값을 반환합니다.

  cehckArray(array1, array2) {
    for (let i = 0; i < array1.length; i++) {
      for (let j = 0; j < array2.length; j++) {
        if (array1[i] === array2[j]) {
          return true;
        }
      }
    }
    // Return if no common element exist 
    return false;
  }

0

이 시도

function arraysEqual(arr1, arr2){
    if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length!=arr2.length)
        return false;

    return arr1.length==arr1.filter(word => arr2.includes(word)).length;
}

0

받아 들인 대답에 따라 다른 방법이 있습니다.

function compareArrays(array1, array2) {

    if (
        !Array.isArray(array1)
        || !Array.isArray(array2)
        || array1.length !== array2.length
    ) return false;

    var first = array1.sort().map(value => (String(value))).join();
    var second = array2.sort().map(value => (String(value))).join();

    return first == second ? true : false;
}

안녕하세요, StackOverflow에 오신 것을 환영합니다! 이 답변은 경우에 따라 작동하지만 그렇지 않은 특정 경우가 있습니다. 먼저 .sort ()가 원래 배열을 수정한다는 점에 유의하십시오. 요즘은 위생 상태가 좋지 않은 것으로 간주되므로 원래 답변이 먼저 .concat ()을 사용하여 복사본을 만듭니다.
Carlos Precioso

두 번째로, 이것은 나머지 자바 스크립트와 일관되게 작동하지 않습니다. {foo : "bar"} === {foo : "bar"}는 false를 반환합니다 (개별적으로 생성 된 두 개의 개별 객체입니다). 따라서 compareArrays ([{foo : "bar"}], [{foo : "bar"}])도 일관성을 위해 false를 반환해야합니다. 그러나 구현시 객체의 문자열 표현이 동일하므로 true를 반환합니다. 그것은 바람직한 행동 일 수도 있고 아닐 수도 있지만, 어떤 경우에도 염두에 두어야 할 행동입니다.
Carlos Precioso

0

두 배열을 비교하여 두 배열이 동일한 요소를 가지고 있는지 확인하는 함수입니다. 고장 나더라도 ...

단순한 배열에 좋습니다. [문자열, 번호, 부울, 널, NaN].

.sort ()를 사용하지 않고 원래 배열을 수정합니다. 어떤 사람들은 그것이 나쁘다고 말합니다 ...

주의. 이 함수는 제한되어 있으므로 Objects "[], {}"또는 이러한 배열 내의 함수를 비교할 수 없습니다. 자체 배열은 Object입니다.

   let arraysHasSameElements = (arr1, arr2) => {
        let count =
            // returns counting of occurrences.
            (arr, val) => arr.reduce((count, curr) => (curr === val ? 1 : 0) + count, 0);

        /* this will return true if lengths of the arrays is equal.
           then compare them.*/
        return arr1.length === arr2.length

            // compare arr1 against arr2.
            && arr1.reduce((checks, val) =>

                /*  creating array of checking if a value has equal amount of occurrences
                    in both arrays, then adds true 'check'. */
                checks.concat(count(arr1, val) === count(arr2, val)), [])

                // checking if each check is equal to true, then .every() returns true.
                .every(check => check);
    }

    let arr1 = ['',-99,true,NaN,21,null,false,'help',-99,'help',NaN], 
        arr2 = [null,-99,'',NaN,NaN,false,true,-99,'help',21,'help'];
    arraysHasSameElements(arr1, arr2); //true

    let arr3 = [false,false,false,false,false,false], 
        arr4 = [false,false,false,false,false,false]
    arraysHasSameElements(arr3, arr4); //true


    // here we have uncommented version.
    let arraysHasSameElements = (arr1, arr2) => {
        let count = (arr, val) => arr.reduce((count, curr) => (curr === val ? 1:0) + count, 0);
        return arr1.length === arr2.length && arr1.reduce((checks, val) =>
            checks.concat(count(arr1, val) === count(arr2, val)), []).every(check => check);
    }

-1

두 어레이를 비교하는 간단한 솔루션 :

var array1 = [2, 4];
var array2 = [4, 2];

array1.sort();
array2.sort();

if (array1[0] == array2[0]) {
    console.log("Success");
}else{
    console.log("Wrong");
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.