Con Jasmine c'è un modo per verificare se 2 array contengono gli stessi elementi, ma non sono necessariamente nello stesso ordine? cioè
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Con Jasmine c'è un modo per verificare se 2 array contengono gli stessi elementi, ma non sono necessariamente nello stesso ordine? cioè
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Risposte:
Se sono solo numeri interi o altri valori primitivi, puoi sort()
inserirli prima del confronto.
expect(array1.sort()).toEqual(array2.sort());
Se i suoi oggetti, combinalo con la map()
funzione per estrarre un identificatore che verrà confrontato
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
accade sul posto, però. (muta l'istanza su cui è chiamato)
sort
prende una funzione opzionale che può usare per fare il confronto.
jasmine versione 2.8 e successive ha
jasmine.arrayWithExactContents()
Il che prevede che un array contenga esattamente gli elementi elencati, in qualsiasi ordine.
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqual(jasmine.arrayWithExactContents(array2))
semplice...
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqual(jasmine.arrayContaining(array2));
Potresti usare wait.arrayContain (array) dallo standard jest:
const expected = ['Alice', 'Bob'];
it('matches even if received contains additional elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
});
// 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
invece di .map
per risparmiare tempo e un po 'di memoria.
array1 = [1, 2]
,array2 = [1, 1]
[1,1,2]
e [1,2,2]
? Forse usando una mappa per ognuno o qualcosa del genere? ad es. array1.reduce((map, item) => { map.set(item, (map.get(item) || 0) + 1)), new Map())
per entrambi gli array, quindi passare in rassegna e verificare che gli importi siano gli stessi? Sembra che ci siano molte iterazioni ma sarebbe più approfondito.
Il pacchetto jest-extended ci fornisce poche asserzioni per semplificare i nostri test, è meno dettagliato e per i test falliti l'errore è più esplicito.
In questo caso potremmo usare 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
})
}
L'idea qui è di determinare prima se la lunghezza dei due array è la stessa, quindi controllare se tutti gli elementi sono nell'array dell'altro.
equal([1, 1, 2], [1, 2, 2])
resi true
.
Ecco una soluzione che funzionerà per qualsiasi numero o array
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)),
);
Alcuni test (alcune risposte a questa domanda non tengono conto di array con più elementi dello stesso valore, quindi [1, 2, 2] e [1, 2] restituirebbero erroneamente 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
Questo algoritmo è ottimo per gli array in cui ogni elemento è unico. In caso contrario, puoi aggiungere qualcosa per verificare la presenza di duplicati ...
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;
}
Questo approccio ha prestazioni di runtime nel caso peggiore teorico peggiore, ma, poiché non esegue alcuna scrittura sull'array, potrebbe essere più veloce in molte circostanze (prestazioni non ancora testate):
ATTENZIONE: come Torben ha sottolineato nei commenti, questo approccio funziona solo se entrambi gli array hanno elementi unici (non ripetitivi) (proprio come molte altre risposte qui).
/**
* 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
ordina gli array sul posto.
Attualmente esiste un matcher per questo USE CASE:
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
, cioè, non disponibile come funzionalità di base di Jest, giusto?
Potresti usare qualcosa come:
expect(array1).toEqual(jasmine.arrayContaining(array2));
Ricorda importazione jasmine
. Oppure aggiungilo al tuo file.eslintrc
Jest ha una funzione chiamata expect.arrayContaining
che farà esattamente quello che vuoi:
expect(array1).toEqual(expect.arrayContaining(array2))
potresti voler controllare se hanno anche la stessa lunghezza, poiché il test passerà se
l'array atteso è un sottoinsieme dell'array ricevuto
secondo il doc.
EDIT: Mi dispiace di non aver notato il tag jasmine, questo è un modo che funziona con Jest
expect(array1.sort()).toEqual(array2.sort());
?