Con Jasmine, ¿hay alguna manera de probar si 2 matrices contienen los mismos elementos, pero no están necesariamente en el mismo orden? es decir
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Con Jasmine, ¿hay alguna manera de probar si 2 matrices contienen los mismos elementos, pero no están necesariamente en el mismo orden? es decir
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Respuestas:
Si son solo números enteros u otros valores primitivos, puede sort()
usarlos antes de comparar.
expect(array1.sort()).toEqual(array2.sort());
Si sus objetos, combínelo con la map()
función para extraer un identificador que se comparará
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
embargo, vale la pena señalar que eso ocurre en el lugar. (muta la instancia en la que se llama)
sort
toma una función opcional que puede usar para hacer la comparación.
jasmine versión 2.8 y posterior tiene
jasmine.arrayWithExactContents()
Lo que espera que una matriz contenga exactamente los elementos enumerados, en cualquier orden.
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqual(jasmine.arrayWithExactContents(array2))
sencillo...
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
lugar de .map
para ahorrar tiempo y mucha memoria.
array1 = [1, 2]
,array2 = [1, 1]
[1,1,2]
y [1,2,2]
? ¿Quizás usar un mapa para cada uno o algo así? por ejemplo, array1.reduce((map, item) => { map.set(item, (map.get(item) || 0) + 1)), new Map())
para ambas matrices, luego recorrerlas y verificar que las cantidades sean las mismas. Parece que hay muchas iteraciones, pero sería más completo.
Puede usar wait.arrayContaining (matriz) de broma estándar:
const expected = ['Alice', 'Bob'];
it('matches even if received contains additional elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
});
El paquete jest-extended nos proporciona pocas afirmaciones para simplificar nuestras pruebas, es menos detallado y para las pruebas fallidas, el error es más explícito.
Para este caso podríamos utilizar 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
})
}
La idea aquí es determinar primero si la longitud de las dos matrices es la misma, luego verificar si todos los elementos están en la matriz de la otra.
equal([1, 1, 2], [1, 2, 2])
devoluciones true
.
Aquí hay una solución que funcionará para cualquier número o matriz.
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)),
);
Algunas pruebas (algunas respuestas a esta pregunta no tienen en cuenta las matrices con varios elementos del mismo valor, por lo que [1, 2, 2] y [1, 2] devolverían verdadero incorrectamente)
[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
Este algoritmo es ideal para matrices en las que cada elemento es único. Si no es así, puede agregar algo para verificar si hay duplicados ...
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;
}
Este enfoque tiene un peor rendimiento teórico en el peor de los casos en tiempo de ejecución, pero, debido a que no realiza ninguna escritura en la matriz, podría ser más rápido en muchas circunstancias (aún no se ha probado el rendimiento):
ADVERTENCIA: Como señaló Torben en los comentarios, este enfoque solo funciona si ambas matrices tienen elementos únicos (no repetidos) (al igual que varias de las otras respuestas aquí).
/**
* 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
ordena las matrices en el lugar.
Actualmente hay un emparejador 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' }]);
});
Podrías usar algo como:
expect(array1).toEqual(jasmine.arrayContaining(array2));
Recuerde importar jasmine
. O agréguelo a su.eslintrc
Jest tiene una función llamada expect.arrayContaining
que hará exactamente lo que quieras:
expect(array1).toEqual(expect.arrayContaining(array2))
es posible que desee verificar si también tienen la misma longitud, ya que la prueba pasará si
la matriz esperada es un subconjunto de la matriz recibida
según el doc.
EDITAR: Lo siento, no me di cuenta de la etiqueta de jazmín, esta es una forma en que funciona con Jest
expect(array1.sort()).toEqual(array2.sort());
?