순서를 무시하고 배열이 같을 것으로 예상


95

Jasmine을 사용하면 두 배열에 동일한 요소가 포함되어 있지만 반드시 동일한 순서가 아닌지 테스트하는 방법이 있습니까? 즉

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

expect(array1).toEqualIgnoreOrder(array2);//should be true

24
expect(array1.sort()).toEqual(array2.sort());?
raina77ow

@ raina77ow 나는 그것도 작동 할 것이라고 생각한다.
David 말한다 Reinstate Monica

1
대답을해야합니까?
raina77ow

1
@ raina77ow 객체의 배열 일 때 조금 더 복잡해집니다. Jasmine이 이것을 위해 상자에서 뭔가를 가지고 있다면 좋을 것입니다.
David 말한다 Reinstate Monica

2
나는 jasmine 자체에서 훌륭한 것을 찾지 못했기 때문에 실제로 lodash (또는 밑줄 / 다른 js 컬렉션 라이브러리를 사용할 수 있음)를 이와 같은 것을 위해 내 테스트 프로젝트에 도입했습니다.
ktharsis

답변:


65

정수 또는 기타 기본 값인 경우 sort()비교하기 전에 할 수 있습니다.

expect(array1.sort()).toEqual(array2.sort());

객체의 경우 map()비교할 식별자를 추출하기 위해 함수 와 결합합니다.

array1 = [{id:1}, {id:2}, {id:3}];
array2 = [{id:3}, {id:2}, {id:1}];

expect(array1.map(a => a.id).sort()).toEqual(array2.map(a => a.id).sort());

기본 배열 정렬 방법은 숫자에 문자열 비교를 사용합니다. "10" < "2" === true
Shmiddty

[10, 2, 1].sort() ---> [1, 10, 2]
Shmiddty

9
@Shmiddty 나는이 경우에 그것이 어떻게 중요한지 보지 못합니다. 순서가 두 어레이 모두 동일하다면 괜찮을 것입니다.
Coloured Panda

1
공정한 포인트. sort하지만 제자리에서 발생 한다는 점은 주목할 가치가 있습니다. (그것이 호출 된 인스턴스를 변경합니다)
Shmiddty

1
이 답변의 객체 부분은 매핑 된 배열 만 비교하기 때문에 실제로 객체가 일치하는지 확인하지 않습니다. 지도가 필요하지 않으며 sort비교를 수행하는 데 사용할 수있는 선택적 함수를 사용합니다.
slifty

22

jasmine 버전 2.8 이상은

jasmine.arrayWithExactContents()

배열에 나열된 요소가 순서에 상관없이 정확히 포함되어있을 것으로 예상합니다.

array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqual(jasmine.arrayWithExactContents(array2))

참조 https://jasmine.github.io/api/3.4/jasmine.html를


13

단순한...

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

expect(array1).toEqual(jasmine.arrayContaining(array2));

7
좋은 대답입니다! 또한 길이가 같은지 확인해야합니다. 그렇지 않으면 [1,2,3,4] 및 [3,2,1]에 대해 거짓 긍정이 발생합니다.
Kristian Hanekamp

11

표준 jest에서 expect.arrayContaining (array)를 사용할 수 있습니다.

  const expected = ['Alice', 'Bob'];
  it('matches even if received contains additional elements', () => {
    expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
  });

완벽한 솔루션! 이것은 선택된 답변이어야합니다 ..
rohit_wason

이것이 가장 좋은 대답 인 것 같습니다.
cevaris

10
// check if every element of array2 is element of array1
// to ensure [1, 1] !== [1, 2]
array2.forEach(x => expect(array1).toContain(x))

// check if every element of array1 is element of array2
// to ensure [1, 2] !== [1, 1]
array1.forEach(x => expect(array2).toContain(x))

// check if they have equal length to ensure [1] !== [1, 1]
expect(array1.length).toBe(array2.length)

2
.forEach대신 사용 .map하여 시간과 메모리를 절약 하십시오 .
Darkhogg

1
안타깝게도 다음 어레이는 서로 다르더라도 통과 할 것입니다. array1 = [1, 2],array2 = [1, 1]
redbmk

2
좋은 캐치 @redbmk 나는 이것에 대한 수표를 추가했습니다, 감사합니다!
Jannic Beck

여전히 문제가 있다고 생각합니다. 어레이가 [1,1,2]있고 [1,2,2]? 어쩌면 각각에 대해지도를 사용할까요? 예 array1.reduce((map, item) => { map.set(item, (map.get(item) || 0) + 1)), new Map())를 들어 두 배열 모두에 대해 루프를 반복하고 금액이 동일한 지 확인하십시오. 많은 반복처럼 보이지만 더 철저 할 것입니다.
redbmk

컨트롤 배열의 제외를 사용할 수 있지만 (찾으면 요소를 제거하고 마지막에 길이가 0인지 확인) 일반적인 경우에는 노력할 가치가 없습니다.
lifecoder

2

농담-확장 패키지는 덜 자세한이고 테스트를하지 못해 오류가 더 명시 적입니다, 우리의 테스트를 단순화하기 위해 우리에게 몇 가지 주장을 제공합니다.

이 경우 toIncludeSameMembers를 사용할 수 있습니다 .

expect([{foo: "bar"}, {baz: "qux"}]).toIncludeSameMembers([{baz: "qux"}, {foo: "bar"}]);

1
//Compare arrays without order
//Example
//a1 = [1, 2, 3, 4, 5]
//a2 = [3, 2, 1, 5, 4]
//isEqual(a1, a2) -> true
//a1 = [1, 2, 3, 4, 5];
//a2 = [3, 2, 1, 5, 4, 6];
//isEqual(a1, a2) -> false


function isInArray(a, e) {
  for ( var i = a.length; i--; ) {
    if ( a[i] === e ) return true;
  }
  return false;
}

function isEqArrays(a1, a2) {
  if ( a1.length !== a2.length ) {
    return false;
  }
  for ( var i = a1.length; i--; ) {
    if ( !isInArray( a2, a1[i] ) ) {
      return false;
    }
  }
  return true;
}

0
function equal(arr1, arr2){
    return arr1.length === arr2.length
    &&
    arr1.every((item)=>{
        return arr2.indexOf(item) >-1
    }) 
    &&
    arr2.every((item)=>{
        return arr1.indexOf(item) >-1
    })
}

여기서 아이디어는 먼저 두 배열의 길이가 동일한 지 확인한 다음 모든 요소가 다른 배열에 있는지 확인하는 것입니다.


이것은 항목의 빈도를 고려하지 않습니다 : equal([1, 1, 2], [1, 2, 2])returns true.
MarkMYoung dec.

0

다음은 모든 수 또는 배열에서 작동하는 솔루션입니다.

https://gist.github.com/tvler/cc5b2a3f01543e1658b25ca567c078e4

const areUnsortedArraysEqual = (...arrs) =>
  arrs.every((arr, i, [first]) => !i || arr.length === first.length) &&
  arrs
    .map(arr =>
      arr.reduce(
        (map, item) => map.set(item, (map.get(item) || 0) + 1),
        new Map(),
      ),
    )
    .every(
      (map, i, [first]) =>
        !i ||
        [...first, ...map].every(([item]) => first.get(item) === map.get(item)),
    );

일부 테스트 (이 질문에 대한 몇 가지 답변은 동일한 값의 여러 항목이있는 배열을 고려하지 않으므로 [1, 2, 2] 및 [1, 2]가 true를 잘못 반환 함)

[1, 2] true
[1, 2], [1, 2] true
[1, 2], [1, 2], [1, 2] true
[1, 2], [2, 1] true
[1, 1, 2], [1, 2, 1] true
[1, 2], [1, 2, 3] false
[1, 2, 3, 4], [1, 2, 3], [1, 2] false
[1, 2, 2], [1, 2] false
[1, 1, 2], [1, 2, 2] false
[1, 2, 3], [1, 2], [1, 2, 3] false

0

이 알고리즘은 각 항목이 고유 한 배열에 적합합니다. 그렇지 않은 경우 중복을 확인하기 위해 무언가를 추가 할 수 있습니다.

tests = [
  [ [1,0,1] , [0,1,1] ],
  [ [1,0,1] , [0,0,1] ], //breaks on this one...
  [ [2,3,3] , [2,2,3] ], //breaks on this one also...
  [ [1,2,3] , [2,1,3] ],
  [ [2,3,1] , [1,2,2] ],
  [ [2,2,1] , [1,3,2] ]
]

tests.forEach(function(test) {
  console.log('eqArraySets( '+test[0]+' , '+test[1]+' ) = '+eqArraySets( test[0] , test[1] ));
});


function eqArraySets(a, b) {
	if ( a.length !== b.length ) { return false; }
	for ( var i = a.length; i--; ) {
		if ( !(b.indexOf(a[i])>-1) ) { return false; }
		if ( !(a.indexOf(b[i])>-1) ) { return false; }
	}
	return true;
}


0

이 접근 방식은 이론적으로 최악의 경우 런타임 성능이 좋지 않지만 어레이에서 쓰기를 수행하지 않기 때문에 많은 상황에서 더 빠를 수 있습니다 (아직 성능을 테스트하지 않았습니다).

경고 : Torben이 주석에서 지적했듯이이 접근 방식은 두 배열에 고유 한 (반복되지 않는) 요소가있는 경우에만 작동합니다 (여기에있는 여러 답변과 마찬가지로).

/**
 * Determine whether two arrays contain exactly the same elements, independent of order.
 * @see /programming/32103252/expect-arrays-to-be-equal-ignoring-order/48973444#48973444
 */
function cmpIgnoreOrder(a, b) {
  const { every, includes } = _;
  return a.length === b.length && every(a, v => includes(b, v));
}

// the following should be all true!
const results = [
  !!cmpIgnoreOrder([1,2,3], [3,1,2]),
  !!cmpIgnoreOrder([4,1,2,3], [3,4,1,2]),
  !!cmpIgnoreOrder([], []),
  !cmpIgnoreOrder([1,2,3], [3,4,1,2]),
  !cmpIgnoreOrder([1], []),
  !cmpIgnoreOrder([1, 3, 4], [3,4,5])
];

console.log('Results: ', results)
console.assert(_.reduce(results, (a, b) => a && b, true), 'Test did not pass!');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>


1
많은 복사본을 만든다는 것은 무슨 의미입니까? Array#sort배열을 제자리에서 정렬합니다.
philraj

1
다음 어레이에 대해 실패합니다 : [1,1,2,3], [3,3,1,2].
Torben Kohlmeier 2018

1
@TorbenKohlmeier 덕분에, 나는 (고유하지 않은 배열에 관해서 인정 패배) 내 대답을 업데이 트
도미


-1

다음과 같이 사용할 수 있습니다.

expect(array1).toEqual(jasmine.arrayContaining(array2));

import를 기억하십시오 jasmine. 또는 귀하의.eslintrc


-4

Jest에는 expect.arrayContaining원하는 것을 정확히 수행 하는 함수 가 있습니다.

expect(array1).toEqual(expect.arrayContaining(array2))

길이가 같은지 확인하는 것이 좋습니다.

예상되는 배열은 수신 된 배열의 하위 집합입니다.

문서에 따르면.

편집 : 재스민 태그를 알아 차리지 못해 죄송합니다. 이것은 Jest 와 함께 작동하는 방법입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.