lodash를 사용하여 배열 비교 (순서없이 항목 존재)


125

루프를 사용하여 할 수 있다는 것을 알고 있지만 우아한 방법을 찾으려고합니다.

두 개의 배열이 있습니다.

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];

lodash위의 두 배열이 동일한 지 확인하는 데 사용하고 싶습니다 . '동일'이란에 array1포함되지 않은 항목이 없음을 의미합니다 array2.

이러한 항목 간의 동등성을 확인하는 측면에서 :

['a', 'b'] == ['b', 'a'] 

또는

['a', 'b'] == ['a', 'b'] 

편지가 항상 순서대로 있기 때문에 둘 다 작동합니다.

답변:


224

외부 배열을 정렬하면 _.isEqual()내부 배열이 이미 정렬되어 있으므로 사용할 수 있습니다 .

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];
_.isEqual(array1.sort(), array2.sort()); //true

참고 .sort()배열을 변이 것입니다. 이것이 문제가되는 경우 먼저 (예 .slice():) 또는 스프레드 연산자 ( ...)를 사용하여 복사 하십시오 .

또는 Daniel Budick이 아래 댓글에서 권장하는대로 수행하십시오.

_.isEqual(_.sortBy(array1), _.sortBy(array2))

Lodash sortBy()는 배열을 변경하지 않습니다.


6
array.sort ()가 원래 배열을 변경하고 있음을 고려하십시오. 아마도 이것이 더 나을 것입니다 : var array1 = [[ 'a', 'b'], [ 'b', 'c']]; var array2 = [[ 'b', 'c'], [ 'a', 'b']]; _.isEqual ([... array1] .sort (), [... array2] .sort ()); // true
Yaniv Efraim

3
.sort()사용자에게 문제가되는 경우 먼저 복사 옵션을 제안 하고 변경 하는 두 문장을 추가했습니다 .
Trott 2011

6
이미 lodash를 사용하고 있다면 _.isEqual(_.sortBy(array1), _sortBy(array2))돌연변이를 방지하기 위해 할 수 있습니다 .
Daniel Budick

1
@DanielBudick 감사합니다! 나는 그것을 대답에 추가했습니다. 좋은 제안입니다.
Trott

33

이를 xor위해 lodashs 를 사용할 수 있습니다.

doArraysContainSameElements = _.xor(arr1, arr2).length === 0

배열 [1, 1]이 배열 [1]과 다르다고 생각하면 다음과 같이 성능을 약간 향상시킬 수 있습니다.

doArraysContainSameElements = arr1.length === arr2.length === 0 && _.xor(arr1, arr2).length === 0

1
어쨌든 배열을 정렬해야합니다.
Sovattha Sok

1
이 새 버전에 대한 더 나은 방법이 있어야한다
레오나르도

@Sovattha Sok 배열을 정렬 할 필요가 없습니다. 그렇게하면 _.xor([3,4], [4,3]).length == 0진실을 얻을 수 있습니다.
Nikolay

1
주의 사항 :이 기술은 "작은"배열에 잘 작동하지만 배열이 거대하고 _.xor ()가 첫 번째 차이를지나 계속 지나쳐지나 가기 때문에 대부분 다른 경우 성능과 메모리 측면에서 고통 스러울 수 있습니다. 즉, 첫 번째 차이가 감지되면 빠르게 반환되지 않습니다.
XDS

6

'동일'이란 array2에 포함되지 않은 array1에 항목이 없음을 의미합니다.

항목이있는 경우 당신은 상관하지 않는 경우 잘 작동이에 대한 ()과 차이를 (), 평평하게 사용할 수 없습니다 에가 . 당신이 묻는 것처럼 들립니다 array1이 array2의 하위 집합 입니까?array2array1

var array1 = [['a', 'b'], ['b', 'c']];
var array2 = [['b', 'c'], ['a', 'b']];

function isSubset(source, target) {
    return !_.difference(_.flatten(source), _.flatten(target)).length;
}

isSubset(array1, array2); // → true
array1.push('d');
isSubset(array1, array2); // → false
isSubset(array2, array1); // → true

4

여기에 이미 답변이 있지만 여기에 순수한 JS 구현이 있습니다. 최적인지 확실하지 않지만 투명하고 읽기 쉽고 간단합니다.

// Does array a contain elements of array b?
const contains = (a, b) => new Set([...a, ...b]).size === a.length
const isEqualSet = (a, b) => contains(a, b) && contains(b, a)

의 이론적 근거는의 모든 요소를 ​​포함 contains()하는 경우 동일한 세트에 넣으면 크기가 변경되지 않는다는 것입니다.ab

예를 들어, if const a = [1,2,3,4]and const b = [1,2], then new Set([...a, ...b]) === {1,2,3,4}. 보시다시피 결과 집합에는 a.

여기에서 더 간결하게하기 위해 다음과 같이 요약 할 수 있습니다.

const isEqualSet = (a, b) => {
  const unionSize = new Set([...a, ...b])
  return unionSize === a.length && unionSize === b.length
}

1

PURE JS (배열 및 하위 배열에 임의 순서의 요소가 2 개 이상있는 경우에도 작동합니다). 문자열이 포함되어있는 경우 ,로 사용 join('-')(UTF 될 수 있습니다) parametr 문자 문자열에 사용하지 않는

array1.map(x=>x.sort()).sort().join() === array2.map(x=>x.sort()).sort().join()


0

_.difference함수를 사용 하여 차이가 있는지 확인할 수 있습니다 .

function isSame(arrayOne, arrayTwo) {
   var a = _.unique(arrayOne),
       b = _.unique(arrayTwo);

   if (a.length <= b.length) {
      a = arrayTwo;
      b = arrayOne;
      return _.isEmpty(_.difference(a.sort(), b.sort()));
   } else {
      return false;
   }

}

// examples
console.log(isSame([1, 2, 3], [1, 2, 3])); // true
console.log(isSame([1, 2, 4], [1, 2, 3])); // false
console.log(isSame([1, 2], [2, 3, 1])); // false
console.log(isSame([2, 3, 1], [1, 2])); // false

// Test cases pointed by Mariano Desanze, Thanks.
console.log(isSame([1, 2, 3], [1, 2, 2])); // false
console.log(isSame([1, 2, 2], [1, 2, 2])); // true
console.log(isSame([1, 2, 2], [1, 2, 3])); // false

도움이 되길 바랍니다.


5
잘못된, 당신의 기능은 얻을 것이다 true위한console.log(isSame([1,2], [2,3,1]));
데이비드 린

3
@DavidLin에게 지적 해 주셔서 감사합니다. 이 경우를 고려하여 변경했습니다. 감사합니다. 불편을 드려 죄송합니다.
Amitesh

2
길이가 같지 않으면 a와 b의 위치를 ​​바꿀 필요가 없습니다. 길이가 다르면 이미 같을 수 없으므로 if (arrayOne.lenght! == arrayTwo.lenght)는 false를 반환합니다.
Alex

1
-1 그것들 ab변수 를 갖는 것은 의미가 없습니다 . 당신은 단지 내에서 그 변수를 사용하는 if-then부분, 그리고 당신이 제일 먼저 나는 다음과 같은 한 줄이 정확히 같은 일을 생각 라인 (2)에로드 된 값이 폐기된다 return arrayOne.length <= arrayTwo.length && _.isEmpty(_.difference(arrayTwo.sort(), arrayTwo.sort());. 그리고는 <=또한으로 개선 할 수있다 ===.
Mariano Desanze 2019 년

1
그리고 _.difference첫 번째 인수의 누락 된 항목을 반환하지만 두 번째 인수의 누락 된 항목은 반환하지 않습니다. 따라서 true1st in 2nd : 항목을 반복 할 때 잘못 반환 됩니다 isSame([1, 2, 3], [1, 2, 2]).
Mariano Desanze 2010 년

0

편집 :이 질문의 다차원 적 측면을 놓쳤으므로 사람들이 1 차원 배열을 비교하는 데 도움이 될 수 있도록 여기에 남겨 둡니다.

오래된 질문이지만 .sort()또는 사용 속도에 문제가 sortBy()있으므로 대신 이것을 사용했습니다.

function arraysContainSameStrings(array1: string[], array2: string[]): boolean {
  return (
    array1.length === array2.length &&
    array1.every((str) => array2.includes(str)) &&
    array2.every((str) => array1.includes(str))
  )
}

빨리 실패하도록 의도되었으며 내 목적에 따라 잘 작동합니다.


마지막 확인이 정말 필요한가요? array1.every((str) => array2.includes(str))충분해야합니다. 또한 OP는 lodash를 사용하기를 원했습니다. 적어도 vanillaJS 솔루션을 제안하는 이유를 말해야합니다 (... 이제 우리는 모든 것을 포함하고 있습니다 ...). 제공된 문제 (2 차원 배열)에 함수를 적용하는 방법의 예도 제공하십시오.
line-o

그것은 좋은 지적이다. 나는 그것의 다차원 적 측면을 다루지 않았고, lodash에 대한 요구 사항이 아니다. 나는 lodash methods to compare arrays without considering order현대 자바 스크립트에서 대안을 찾기 위해 (내가했던 것처럼) 누구든지 검색하는 것이 유용 할 것이라고 생각했다 . arraysContainSameStrings(['1', '2', '2'], ['1', '2', '3'])그렇지 않으면 true를 반환 하므로 두 번째 확인이 필요 합니다. 도움이 될 수 있으므로 여기에 남겨 두겠습니다.하지만 질문에 답하지 않은 것에 감사드립니다
charliematters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.