Gibt es mit Jasmine eine Möglichkeit zu testen, ob 2 Arrays dieselben Elemente enthalten, aber nicht unbedingt in derselben Reihenfolge? dh
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Gibt es mit Jasmine eine Möglichkeit zu testen, ob 2 Arrays dieselben Elemente enthalten, aber nicht unbedingt in derselben Reihenfolge? dh
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqualIgnoreOrder(array2);//should be true
Antworten:
Wenn es sich nur um Ganzzahlen oder andere primitive Werte handelt, können Sie sort()
diese vor dem Vergleich verwenden.
expect(array1.sort()).toEqual(array2.sort());
Wenn es sich um Objekte handelt, kombinieren Sie es mit der map()
Funktion, um einen zu vergleichenden Bezeichner zu extrahieren
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
dies an Ort und Stelle geschieht. (es mutiert die Instanz, auf der es aufgerufen wird)
sort
eine optionale Funktion, mit der der Vergleich durchgeführt werden kann.
Jasmin Version 2.8 und höher hat
jasmine.arrayWithExactContents()
Was erwartet, dass ein Array genau die aufgelisteten Elemente in beliebiger Reihenfolge enthält.
array1 = [1,2,3];
array2 = [3,2,1];
expect(array1).toEqual(jasmine.arrayWithExactContents(array2))
einfach...
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
stattdessen .map
, um Zeit und Speicherplatz zu sparen.
array1 = [1, 2]
,array2 = [1, 1]
[1,1,2]
und sind [1,2,2]
? Vielleicht eine Karte für jede oder etwas? zB array1.reduce((map, item) => { map.set(item, (map.get(item) || 0) + 1)), new Map())
für beide Arrays, dann durchlaufen Sie sie und überprüfen Sie, ob die Beträge gleich sind? Scheint wie viele Iterationen, wäre aber gründlicher.
Sie könnten expected.arrayContaining (Array) aus Standard-Scherz verwenden:
const expected = ['Alice', 'Bob'];
it('matches even if received contains additional elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
});
Das Jest-Extended- Paket enthält nur wenige Aussagen zur Vereinfachung unserer Tests. Es ist weniger ausführlich und bei fehlgeschlagenen Tests ist der Fehler expliziter.
In diesem Fall könnten wir toIncludeSameMembers verwenden
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
})
}
Die Idee hier ist, zuerst festzustellen, ob die Länge der beiden Arrays gleich ist, und dann zu überprüfen, ob sich alle Elemente im Array des anderen befinden.
equal([1, 1, 2], [1, 2, 2])
Rücksendungen true
.
Hier ist eine Lösung, die für eine beliebige Anzahl oder Arrays funktioniert
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)),
);
Einige Tests (einige Antworten auf diese Frage berücksichtigen keine Arrays mit mehreren Elementen desselben Werts, sodass [1, 2, 2] und [1, 2] fälschlicherweise true zurückgeben würden)
[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
Dieser Algorithmus eignet sich hervorragend für Arrays, bei denen jedes Element ein Unikat ist. Wenn nicht, können Sie etwas hinzufügen, um nach Duplikaten zu suchen ...
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;
}
Dieser Ansatz weist eine schlechtere theoretische Worst-Case-Laufzeitleistung auf. Da jedoch keine Schreibvorgänge auf dem Array ausgeführt werden, ist er unter vielen Umständen möglicherweise schneller (die Leistung wurde noch nicht getestet):
WARNUNG: Wie Torben in den Kommentaren hervorhob, funktioniert dieser Ansatz nur, wenn beide Arrays eindeutige (sich nicht wiederholende) Elemente haben (genau wie einige der anderen Antworten hier).
/**
* 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
sortiert Arrays an Ort und Stelle.
Derzeit gibt es einen Matcher für diesen 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' }]);
});
Sie könnten etwas verwenden wie:
expect(array1).toEqual(jasmine.arrayContaining(array2));
Denken Sie daran, importieren jasmine
. Oder fügen Sie es Ihrem hinzu.eslintrc
Jest hat eine Funktion namens, expect.arrayContaining
die genau das tut, was Sie wollen:
expect(array1).toEqual(expect.arrayContaining(array2))
Möglicherweise möchten Sie auch überprüfen, ob sie dieselbe Länge haben, da der Test bestanden wird, wenn
Das erwartete Array ist eine Teilmenge des empfangenen Arrays
nach dem doc.
EDIT: Tut mir leid, dass ich das Jasmin-Tag nicht bemerkt habe. Dies ist eine Methode, die mit Jest funktioniert
expect(array1.sort()).toEqual(array2.sort());
?