Com o Jasmine, há uma maneira de testar se 2 arrays contêm os mesmos elementos, mas não estão necessariamente na mesma ordem? ie
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Com o Jasmine, há uma maneira de testar se 2 arrays contêm os mesmos elementos, mas não estão necessariamente na mesma ordem? ie
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Respostas:
Se forem apenas números inteiros ou outros valores primitivos, você pode sort()
colocá-los antes de comparar.
expect(array1.sort()).toEqual(array2.sort());
Se forem objetos, combine-o com a map()
função para extrair um identificador que será comparado
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
[10, 2, 1].sort() ---> [1, 10, 2]
sort
acontece no local, no entanto. (muda a instância na qual é chamado)
sort
tem uma função opcional que pode usar para fazer a comparação.
jasmine versão 2.8 e posterior tem
jasmine.arrayWithExactContents()
Que espera que uma matriz contenha exatamente os elementos listados, em qualquer ordem.
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqual(jasmine.arrayWithExactContents(array2))
simples...
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqual(jasmine.arrayContaining(array2));
// 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)
.forEach
vez de .map
para economizar algum tempo e muita memória.
array1 = [1, 2]
,array2 = [1, 1]
[1,1,2]
e [1,2,2]
? Talvez usando um mapa para cada um ou algo assim? por exemplo, array1.reduce((map, item) => { map.set(item, (map.get(item) || 0) + 1)), new Map())
para ambas as matrizes, então faça um loop através delas e verifique se os valores são iguais Parece muitas iterações, mas seria mais completo.
Você pode usar expect.arrayContaining (array) do jest padrão:
const expected = ['Alice', 'Bob'];
it('matches even if received contains additional elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
});
O pacote jest-extended fornece-nos poucas afirmações para simplificar nossos testes, é menos prolixo e para testes que falham o erro é mais explícito.
Para este caso, poderíamos usar toIncludeSameMembers
expect([{foo: "bar"}, {baz: "qux"}]).toIncludeSameMembers([{baz: "qux"}, {foo: "bar"}]);
//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;
}
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
})
}
A ideia aqui é primeiro determinar se o comprimento das duas matrizes é o mesmo e, em seguida, verificar se todos os elementos estão na outra matriz.
equal([1, 1, 2], [1, 2, 2])
devoluções true
.
Aqui está uma solução que funcionará para qualquer número ou matrizes
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)),
);
Alguns testes (algumas respostas a esta pergunta não levam em consideração matrizes com vários itens do mesmo valor, então [1, 2, 2] e [1, 2] retornariam incorretamente verdadeiro)
[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
Esse algoritmo é ótimo para matrizes em que cada item é único. Se não, você pode adicionar algo para verificar se há duplicatas ...
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;
}
Esta abordagem tem pior desempenho de tempo de execução teórico de pior caso, mas, como não executa nenhuma gravação na matriz, pode ser mais rápida em muitas circunstâncias (ainda não testei o desempenho):
AVISO: Como Torben apontou nos comentários, essa abordagem só funciona se ambos os arrays tiverem elementos exclusivos (não repetitivos) (assim como várias das outras respostas aqui).
/**
* 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>
Array#sort
classifica matrizes no local.
Atualmente existe uma correspondência para este CASO DE USO:
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' }]);
});
jest-extended
, ou seja, não está disponível como uma funcionalidade central do Jest, certo?
Você poderia usar algo como:
expect(array1).toEqual(jasmine.arrayContaining(array2));
Lembre-se de importar jasmine
. Ou adicione ao seu.eslintrc
Jest tem uma função chamada expect.arrayContaining
que fará exatamente o que você quiser:
expect(array1).toEqual(expect.arrayContaining(array2))
você pode querer verificar se eles têm o mesmo comprimento também, uma vez que o teste passará se
a matriz esperada é um subconjunto da matriz recebida
de acordo com o doc.
EDIT: Desculpe não ter notado a etiqueta de jasmim, é uma forma que funciona com Jest
expect(array1.sort()).toEqual(array2.sort());
?