期望数组无效顺序

时间:2015-08-19 18:42:32

标签: javascript jasmine karma-jasmine

使用Jasmine有一种方法可以测试2个数组是否包含相同的元素,但不一定是相同的顺序吗?即

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

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

16 个答案:

答案 0 :(得分:35)

如果它只是整数或其他原始值,那么在比较之前你可以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());

答案 1 :(得分:7)

// 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 :(得分:4)

简单...

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

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

答案 3 :(得分: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;
}

答案 4 :(得分:0)

这种方法的理论最坏情况下运行时性能更差,但是,因为它不对阵列执行任何写操作,所以在许多情况下可能会更快(尚未测试性能):

警告:正如Torben在评论中指出的那样,这种方法只有在两个数组都具有唯一(非重复)元素时才有效(就像这里的其他几个答案一样)。

/**
 * Determine whether two arrays contain exactly the same elements, independent of order.
 * @see https://stackoverflow.com/questions/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>

答案 5 :(得分: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
    })
}

这里的想法是首先确定两个数组的长度是否相同,然后检查所有元素是否都在另一个数组中。

答案 6 :(得分: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

答案 7 :(得分:0)

此算法非常适合每个项目都是唯一的数组。如果没有,您可以添加一些内容来检查重复项...

null

答案 8 :(得分:0)

该使用案例目前有一个匹配器:

https://github.com/jest-community/jest-extended/pull/122/files

test('passes when arrays match in a different order', () => {
  expect([1, 2, 3]).toMatchArray([3, 1, 2]);
  expect([{ foo: 'bar' }, { baz: 'qux' }]).toMatchArray([{ baz: 'qux' }, { foo: 'bar' }]);
});

答案 9 :(得分:0)

茉莉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

答案 10 :(得分:0)

jest-extended软件包为我们提供了一些断言来简化测试,它不那么冗长,并且对于失败的测试,错误更加明确。

在这种情况下,我们可以使用toIncludeSameMembers

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

答案 11 :(得分:0)

您可以使用标准玩笑中的Expect.arrayContaining(array):

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

答案 12 :(得分:0)

我目前正在使用这个辅助函数(用于 TypeScript)。它确保也支持具有非唯一元素的数组。

function expectArraysToBeEqualIgnoringOrder<T>(arr1: T[], arr2: T[]) {

    while(arr1.length > 0) {

        expect(arr1.length).toEqual(arr2.length)

        const elementToDelete = arr1[0]

        arr1 = arr1.filter(element => element !== elementToDelete)
        arr2 = arr2.filter(element => element !== elementToDelete)

    }

    expect(arr2.length).toEqual(0)

}

许多其他回答者没有正确处理这样的情况:

array1: [a, b, b, c]
array2: [a, b, c, c]

这里两个数组中的元素数量相同,两个数组都包含另一个数组中的所有元素,但它们是不同的数组,测试应该失败。 它以 O(n^2) 运行(准确地说是 (n^2 + n) / 2),因此它不适合非常大的数组,但它适用于不易排序的数组,因此无法在 O( n * log(n))

答案 13 :(得分:-1)

您可以使用类似的内容:

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

记住导入jasmine。 或将其添加到您的.eslintrc

答案 14 :(得分:-4)

对于它的价值,你可以在Jest中做到:

>colnames(test)
[1]"X871691600001976087" 
[2]"X871691600001837791"  etc

答案 15 :(得分:-4)

Jest有一个名为expect.arrayContaining的函数,它将完全按照您的要求进行操作:

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

您可能还要检查它们的长度是否相同,因为如果通过,测试会通过

期望的数组是接收到的数组的子集

根据文档。

编辑: 抱歉,我没有注意到jasmine标签,这是 Jest

的一种工作方式