Mong đợi Mảng bằng nhau bỏ qua thứ tự


87

Với Jasmine có cách nào để kiểm tra xem 2 mảng có chứa các phần tử giống nhau nhưng không nhất thiết phải cùng thứ tự không? I E

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

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

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

@ raina77ow Tôi đoán điều đó cũng sẽ hoạt động.
David nói Hãy phục hồi Monica vào

1
Tôi có nên biến điều này thành một câu trả lời không?
raina77ow

1
@ raina77ow Nó phức tạp hơn một chút khi nó là một mảng các đối tượng. Sẽ thật tuyệt nếu Jasmine có thứ gì đó ngoài hộp cho việc này.
David nói Hãy phục hồi Monica vào

2
Tôi không tìm thấy bất cứ điều gì tuyệt vời trong bản thân hoa nhài vì vậy thực sự đã giới thiệu lodash (hoặc bạn có thể sử dụng dấu gạch dưới / thư viện sưu tập js khác) vào dự án thử nghiệm của tôi cho những thứ như thế này.
ktharsis

Câu trả lời:


62

Nếu đó chỉ là số nguyên hoặc các giá trị nguyên thủy khác, bạn có thể sort()so sánh chúng trước khi so sánh.

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

Nếu các đối tượng của nó, hãy kết hợp nó với map()hàm để trích xuất một số nhận dạng sẽ được so sánh

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

phương pháp sắp xếp mảng mặc định sử dụng so sánh chuỗi cho các số. "10" < "2" === true
Shmiddty

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

7
@Shmiddty Tôi không thấy nó quan trọng như thế nào trong trường hợp này. Miễn là thứ tự giống nhau cho cả hai mảng, nó sẽ ổn.
Gấu trúc màu

1
Điểm công bằng. Điều đáng chú ý là sortxảy ra tại chỗ. (nó thay đổi phiên bản mà nó được gọi)
Shmiddty

1
Phần đối tượng của câu trả lời này sẽ không thực sự xác minh rằng các đối tượng khớp với nhau, vì nó chỉ so sánh các mảng được ánh xạ. Bạn không cần bản đồ, hãy sortsử dụng một chức năng tùy chọn mà nó có thể sử dụng để so sánh.
slifty

19

jasmine phiên bản 2.8 trở lên có

jasmine.arrayWithExactContents()

Dự kiến ​​rằng một mảng chứa chính xác các phần tử được liệt kê, theo bất kỳ thứ tự nào.

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

Xem https://jasmine.github.io/api/3.4/jasmine.html


13

đơn giản...

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

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

7
Câu trả lời rất hay! Bạn cũng cần kiểm tra xem độ dài có bằng nhau không, nếu không, bạn sẽ có giá trị dương sai trên [1,2,3,4] và [3,2,1].
Kristian Hanekamp

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
Sử dụng .forEachthay vì .mapđể tiết kiệm thời gian và bộ nhớ.
Darkhogg 19/03/18

1
Đáng tiếc là điều này sẽ vượt qua với các mảng sau đây mặc dù họ là khác nhau: array1 = [1, 2],array2 = [1, 1]
redbmk

2
Rất tốt @redbmk Tôi đã thêm một kiểm tra cho điều này, cảm ơn!
Jannic Beck

Tôi nghĩ rằng vẫn còn một vấn đề - điều gì sẽ xảy ra nếu các mảng [1,1,2][1,2,2]? Có thể sử dụng Bản đồ cho từng cái hay cái gì đó? ví dụ array1.reduce((map, item) => { map.set(item, (map.get(item) || 0) + 1)), new Map())cho cả hai mảng, sau đó lặp qua chúng và kiểm tra xem số lượng có giống nhau không? Có vẻ như rất nhiều lần lặp lại nhưng sẽ kỹ lưỡng hơn.
redbmk

Loại trừ khỏi mảng điều khiển có thể được sử dụng (loại bỏ phần tử khi tìm thấy, sau đó kiểm tra độ dài cuối cùng là 0), nhưng nó không đáng để nỗ lực trong các trường hợp thông thường.
lifeecoder

5

Bạn có thể sử dụngpect.arrayContaining (mảng) từ jest tiêu chuẩn:

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

2

Gói jest mở rộng cung cấp cho chúng tôi một số xác nhận để đơn giản hóa các thử nghiệm của chúng tôi, nó ít dài dòng hơn và đối với các thử nghiệm không thành công, lỗi rõ ràng hơn.

Đối với trường hợp này, chúng tôi có thể sử dụng 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
    })
}

Ý tưởng ở đây là trước tiên xác định xem độ dài của hai mảng có bằng nhau hay không, sau đó kiểm tra xem tất cả các phần tử có nằm trong mảng của mảng kia hay không.


Điều này không tính đến tần suất của các mục: equal([1, 1, 2], [1, 2, 2])trả lại true.
MarkMYoung 13/12/19

0

Đây là một giải pháp sẽ hoạt động cho bất kỳ số hoặc mảng nào

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

Một số bài kiểm tra (một số câu trả lời cho câu hỏi này không tính đến mảng có nhiều mục có cùng giá trị, vì vậy [1, 2, 2] và [1, 2] sẽ trả về true không chính xác)

[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

Thuật toán này rất tốt cho các mảng mà mỗi mục là duy nhất. Nếu không, bạn có thể thêm một cái gì đó vào để kiểm tra các bản sao ...

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

Cách tiếp cận này có hiệu suất thời gian chạy trong trường hợp xấu nhất theo lý thuyết kém hơn, nhưng vì nó không thực hiện bất kỳ lần ghi nào trên mảng, nó có thể nhanh hơn trong nhiều trường hợp (chưa kiểm tra hiệu suất):

CẢNH BÁO: Như Torben đã chỉ ra trong các nhận xét, cách tiếp cận này chỉ hoạt động nếu cả hai mảng đều có các phần tử duy nhất (không lặp lại) (giống như một số câu trả lời khác ở đây).

/**
 * 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
Ý bạn là gì khi bạn nói nó tạo ra rất nhiều bản sao? Array#sortsắp xếp các mảng tại chỗ.
philraj

1
Không cho các mảng này: [1,1,2,3], [3,3,1,2].
Torben Kohlmeier

1
@TorbenKohlmeier Cảm ơn, tôi cập nhật (thất bại thừa nhận liên quan đến mảng không duy nhất) câu trả lời của tôi
Domi


-1

Bạn có thể sử dụng một cái gì đó như:

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

Ghi nhớ nhập jasmine. Hoặc thêm nó vào.eslintrc


-3

Jest có một hàm được gọi expect.arrayContainingsẽ làm chính xác những gì bạn muốn:

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

bạn có thể muốn kiểm tra xem chúng cũng có cùng độ dài hay không, vì bài kiểm tra sẽ vượt qua nếu

mảng mong đợi là một tập hợp con của mảng đã nhận

theo doc.

CHỈNH SỬA: Xin lỗi vì tôi không nhận thấy thẻ hoa nhài, đây là một cách hoạt động với Jest

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.