Ik zou graag twee arrays willen vergelijken … idealiter, efficiënt. Niets bijzonders, gewoon true
als ze identiek zijn, en false
zo niet. Niet verrassend, de vergelijkingsoperator lijkt niet te werken.
var a1 = [1,2,3];
var a2 = [1,2,3];
console.log(a1==a2); // Returns false
console.log(JSON.stringify(a1)==JSON.stringify(a2)); // Returns true
JSON die codeert voor elke array doet, maar is er een snellere of “betere” manier om simpelweg overeenstemming te vergelijken zonder te hoevenen door elke waarde?
1, Autoriteit 100%
Om overeenstemming te vergelijken, loop ze door hen heen en vergelijk elke waarde:
Arrays vergelijken:
// Warn if overriding existing method
if(Array.prototype.equals)
console.warn("Overriding existing Array.prototype.equals. Possible causes: New API defines the method, there's a framework conflict or you've got double inclusions in your code.");
// attach the .equals method to Array's prototype to call it on any array
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}
// Hide method from for-in loops
Object.defineProperty(Array.prototype, "equals", {enumerable: false});
Gebruik:
[1, 2, [3, 4]].equals([1, 2, [3, 2]]) === false;
[1, "2,3"].equals([1, 2, 3]) === false;
[1, 2, [3, 4]].equals([1, 2, [3, 4]]) === true;
[1, 2, 1, 2].equals([1, 2, 1, 2]) === true;
Je zou kunnen zeggen “Maar het is veel sneller om strings te vergelijken – geen lussen…” wel, dan moet je er rekening mee houden dat er lussen ZIJN. Eerste recursieve lus die Array converteert naar string en tweede, die twee strings vergelijkt. Deze methode is dus sneller dan het gebruik van string.
Ik ben van mening dat grotere hoeveelheden gegevens altijd in arrays moeten worden opgeslagen, niet in objecten. Als u echter objecten gebruikt, kunnen ze ook gedeeltelijk worden vergeleken.
Zo gaat het:
Objecten vergelijken:
Ik heb hierboven aangegeven dat twee object instantiesnooit gelijk zullen zijn, zelfs als ze op dit moment dezelfde gegevens bevatten:
({a:1, foo:"bar", numberOfTheBeast: 666}) == ({a:1, foo:"bar", numberOfTheBeast: 666}) //false
Dit heeft een reden, aangezien er bijvoorbeeld privévariabelen binnen objecten kunnen zijn.
Als u echter alleen de objectstructuur gebruikt om gegevens te bevatten, is vergelijken nog steeds mogelijk:
Object.prototype.equals = function(object2) {
//For the first loop, we only check for types
for (propName in this) {
//Check for inherited methods and properties - like .equals itself
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
//Return false if the return value is different
if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
return false;
}
//Check instance type
else if (typeof this[propName] != typeof object2[propName]) {
//Different types => not equal
return false;
}
}
//Now a deeper check using other objects property names
for(propName in object2) {
//We must check instances anyway, there may be a property that only exists in object2
//I wonder, if remembering the checked values from the first loop would be faster or not
if (this.hasOwnProperty(propName) != object2.hasOwnProperty(propName)) {
return false;
}
else if (typeof this[propName] != typeof object2[propName]) {
return false;
}
//If the property is inherited, do not check any more (it must be equa if both objects inherit it)
if(!this.hasOwnProperty(propName))
continue;
//Now the detail check and recursion
//This returns the script back to the array comparing
/**REQUIRES Array.equals**/
if (this[propName] instanceof Array && object2[propName] instanceof Array) {
// recurse into the nested arrays
if (!this[propName].equals(object2[propName]))
return false;
}
else if (this[propName] instanceof Object && object2[propName] instanceof Object) {
// recurse into another objects
//console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
if (!this[propName].equals(object2[propName]))
return false;
}
//Normal value comparison for strings and numbers
else if(this[propName] != object2[propName]) {
return false;
}
}
//If everything passed, let's say YES
return true;
}
Onthoud echter dat deze is bedoeld om JSON-achtige gegevens te vergelijken, niet klasse-instanties en andere dingen. Als je meer gecompliceerde objecten wilt vergelijken, kijk dan naar dit antwoord en de superlange functie.
Om dit te laten werken met Array.equals
moet je de originele functie een beetje aanpassen:
...
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
}
/**REQUIRES OBJECT COMPARE**/
else if (this[i] instanceof Object && array[i] instanceof Object) {
// recurse into another objects
//console.log("Recursing to compare ", this[propName],"with",object2[propName], " both named \""+propName+"\"");
if (!this[i].equals(array[i]))
return false;
}
else if (this[i] != array[i]) {
...
Ik heb een kleine testtool gemaakt voor beide functies.
Bonus: geneste arrays met indexOf
en contains
Samy Bencherif heeftnuttige functies voor het geval u zoekt naar een specifiek object in geneste arrays, die hier beschikbaar zijn: https://jsfiddle .net/SamyBencherif/8352y6yw/
Antwoord 2, autoriteit 51%
Hoewel dit alleen werkt voor scalaire arrays (zie opmerking hieronder), is het kort:
array1.length === array2.length && array1.every(function(value, index) { return value === array2[index]})
Rr, in ECMAScript 6 / CoffeeScript / TypeScript met pijlfuncties:
array1.length === array2.length && array1.every((value, index) => value === array2[index])
(Opmerking: ‘scalar’ betekent hier waarden die direct kunnen worden vergeleken met behulp van ===
. Dus: getallen, strings, objecten door verwijzing, functies door verwijzing. Zie de MDN-referentievoor meer informatie over de vergelijkingsoperators).
UPDATE
Van wat ik uit de opmerkingen heb gelezen, kan het sorteren van de array en het vergelijken een nauwkeurig resultaat opleveren:
const array2Sorted = array2.slice().sort();
array1.length === array2.length && array1.slice().sort().every(function(value, index) {
return value === array2Sorted[index];
});
Bijvoorbeeld:
array1 = [2,3,1,4];
array2 = [1,2,3,4];
Dan zou de bovenstaande code true
geven
3, Autoriteit 26%
Ik hou ervan om de undercore-bibliotheek te gebruiken voor array / object Heavy Codering Projecten … in Undercore en Lodash, ongeacht of u reeksen of objecten vergelijkt, ziet het er gewoon als volgt uit:
_.isEqual(array1, array2) // returns a boolean
_.isEqual(object1, object2) // returns a boolean
4, Autoriteit 10%
In de geest van de oorspronkelijke vraag:
Ik zou graag twee arrays willen vergelijken … idealiter efficiënt . niets
Fancy , gewoon waar als ze identiek zijn en onwaar, zo niet.
Ik heb prestatietests uitgevoerd op enkele van de meer eenvoudige suggesties die hier zijn voorgesteld met de volgende resultaten ( snel om te vertragen):
terwijl (67%) door Tim Down
var i = a1.length;
while (i--) {
if (a1[i] !== a2[i]) return false;
}
return true
elke (69%) door user2782196
a1.every((v,i)=> v === a2[i]);
verlaag (74%) door Deis
a1.reduce((a, b) => a && a2.includes(b), true);
Word lid & amp; TOSTRING (78%) door Gaizka Allende & Amp; vivek
a1.join('') === a2.join('');
a1.toString() === a2.toString();
Half Tostring (90%) door Victor Palomo
a1 == a2.toString();
stringify (100%) door Radtek
JSON.stringify(a1) === JSON.stringify(a2);
Opmerkingde onderstaande voorbeelden gaan ervan uit dat de arrays gesorteerde, eendimensionale arrays zijn.
.length
vergelijking is verwijderd voor een gemeenschappelijke benchmark (voega1.length === a2.length
toe aan een van de suggesties en je krijgt een prestatieverbetering van ~10% ). Kies de oplossingen die voor u het beste werken, wetende wat de snelheid en beperking van elke oplossing is.Niet-gerelateerde opmerking:het is interessant om te zien dat mensen alle schietgrage John Waynes op de neerstemknop krijgen op volkomen legitieme antwoorden op deze vraag.
Antwoord 5, autoriteit 8%
De praktische manier
Ik denk dat het verkeerd is om te zeggen dat een bepaalde implementatie “The Right Way™” is als het alleen maar “goed” (“juist”) is in tegenstelling tot een “foute” oplossing. De oplossing van Tomáš is een duidelijke verbetering ten opzichte van string-gebaseerde array-vergelijking, maar dat betekent niet dat het objectief “juist” is. Wat is goedeigenlijk? Is het de snelste? Is het het meest flexibel? Is het het gemakkelijkst te begrijpen? Is het de snelste om te debuggen? Gebruikt het de minste bewerkingen? Heeft het bijwerkingen? Geen enkele oplossing kan het beste van alle dingen hebben.
Tomáš zou kunnen zeggen dat zijn oplossing snel is, maar ik zou ook zeggen dat het onnodig ingewikkeld is. Het probeert een alles-in-één oplossing te zijn die werkt voor alle arrays, genest of niet. Het accepteert zelfs meer dan alleen arrays als invoer en probeert nog steeds een “geldig” antwoord te geven.
Algemene middelen bieden herbruikbaarheid
Mijn antwoord zal het probleem anders benaderen. Ik zal beginnen met een generieke arrayCompare
-procedure die zich alleen bezighoudt met het doorlopen van de arrays. Van daaruit bouwen we onze andere basisvergelijkingsfuncties zoals arrayEqual
en arrayDeepEqual
, enz.
// arrayCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayCompare = f => ([x,...xs]) => ([y,...ys]) =>
x === undefined && y === undefined
? true
: Boolean (f (x) (y)) && arrayCompare (f) (xs) (ys)
Naar mijn mening heeft de beste soort code zelfs geen commentaar nodig, en dit is geen uitzondering. Er gebeurt hier zo weinig dat u het gedrag van deze procedure bijna zonder enige moeite kunt begrijpen. Natuurlijk, een deel van de ES6-syntaxis lijkt je nu misschien vreemd, maar dat is alleen omdat ES6 relatief nieuw is.
Zoals het type suggereert, neemt arrayCompare
de vergelijkingsfunctie f
en twee invoerarrays, xs
en ys
. Voor het grootste deel hoeven we alleen maar f (x) (y)
aan te roepen voor elk element in de invoerarrays. We retourneren een vroege false
als de door de gebruiker gedefinieerde f
false
retourneert – dankzij de &&
‘s evaluatie van kortsluiting. Dus ja, dit betekent dat de comparator de iteratie vroegtijdig kan stoppen en het doorlussen van de rest van de invoerarray kan voorkomen als dat niet nodig is.
Strikte vergelijking
Vervolgens kunnen we met behulp van onze arrayCompare
-functie gemakkelijk andere functies maken die we mogelijk nodig hebben. We beginnen met de elementaire arrayEqual
…
// equal :: a -> a -> Bool
const equal = x => y =>
x === y // notice: triple equal
// arrayEqual :: [a] -> [a] -> Bool
const arrayEqual =
arrayCompare (equal)
const xs = [1,2,3]
const ys = [1,2,3]
console.log (arrayEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2) && (3 === 3) //=> true
const zs = ['1','2','3']
console.log (arrayEqual (xs) (zs)) //=> false
// (1 === '1') //=> false
Zo simpel is het. arrayEqual
kan worden gedefinieerd met arrayCompare
en een comparatorfunctie die a
vergelijkt met b
met behulp van ===
(voor strikte gelijkheid).
Merk op dat we equal
ook definiëren als zijn eigen functie. Dit benadrukt de rol van arrayCompare
als een functie van hogere orde om onze eerste-orde-vergelijker te gebruiken in de context van een ander gegevenstype (Array).
Losse vergelijking
We zouden net zo gemakkelijk arrayLooseEqual
kunnen definiëren door in plaats daarvan een ==
te gebruiken. Als u nu 1
(nummer) vergelijkt met '1'
(tekenreeks), is het resultaat true
…
// looseEqual :: a -> a -> Bool
const looseEqual = x => y =>
x == y // notice: double equal
// arrayLooseEqual :: [a] -> [a] -> Bool
const arrayLooseEqual =
arrayCompare (looseEqual)
const xs = [1,2,3]
const ys = ['1','2','3']
console.log (arrayLooseEqual (xs) (ys)) //=> true
// (1 == '1') && (2 == '2') && (3 == '3') //=> true
Diepe vergelijking (recursief)
Je hebt waarschijnlijk gemerkt dat dit slechts een oppervlakkige vergelijking is. De oplossing van Tomáš is toch zeker “The Right Way™” omdat het een diepgaande vergelijking impliceert, toch?
Nou, onze arrayCompare
-procedure is veelzijdig genoeg om te gebruiken op een manier die een diepgaande gelijkheidstest een fluitje van een cent maakt …
// isArray :: a -> Bool
const isArray =
Array.isArray
// arrayDeepCompare :: (a -> a -> Bool) -> [a] -> [a] -> Bool
const arrayDeepCompare = f =>
arrayCompare (a => b =>
isArray (a) && isArray (b)
? arrayDeepCompare (f) (a) (b)
: f (a) (b))
const xs = [1,[2,[3]]]
const ys = [1,[2,['3']]]
console.log (arrayDeepCompare (equal) (xs) (ys)) //=> false
// (1 === 1) && (2 === 2) && (3 === '3') //=> false
console.log (arrayDeepCompare (looseEqual) (xs) (ys)) //=> true
// (1 == 1) && (2 == 2) && (3 == '3') //=> true
Zo simpel is het. We bouwen een diepe comparator met behulp van een anderefunctie van hogere orde. Deze keer verpakken we arrayCompare
met een aangepaste comparator die controleert of a
en b
arrays zijn. Als dit het geval is, past u arrayDeepCompare
opnieuw toe, anders vergelijkt u a
en b
met de door de gebruiker opgegeven comparator (f
). Dit stelt ons in staat om het diepe vergelijkingsgedrag gescheiden te houden van hoe we de afzonderlijke elementen daadwerkelijk vergelijken. Dat wil zeggen, zoals het bovenstaande voorbeeld laat zien, kunnen we diep vergelijken met behulp van equal
, looseEqual
of een andere comparator die we maken.
Omdat arrayDeepCompare
gecurryd is, kunnen we het ook gedeeltelijk toepassen zoals in de vorige voorbeelden
// arrayDeepEqual :: [a] -> [a] -> Bool
const arrayDeepEqual =
arrayDeepCompare (equal)
// arrayDeepLooseEqual :: [a] -> [a] -> Bool
const arrayDeepLooseEqual =
arrayDeepCompare (looseEqual)
Voor mij is dit al een duidelijke verbetering ten opzichte van de oplossing van Tomáš, omdat ik explicieteen oppervlakkige of diepe vergelijking voor mijn arrays kan kiezen, indien nodig.
Objectvergelijking (voorbeeld)
Wat als je een array van objecten hebt of zoiets? Misschien wilt u die arrays als “gelijk” beschouwen als elk object dezelfde id
-waarde heeft …
// idEqual :: {id: Number} -> {id: Number} -> Bool
const idEqual = x => y =>
x.id !== undefined && x.id === y.id
// arrayIdEqual :: [a] -> [a] -> Bool
const arrayIdEqual =
arrayCompare (idEqual)
const xs = [{id:1}, {id:2}]
const ys = [{id:1}, {id:2}]
console.log (arrayIdEqual (xs) (ys)) //=> true
// (1 === 1) && (2 === 2) //=> true
const zs = [{id:1}, {id:6}]
console.log (arrayIdEqual (xs) (zs)) //=> false
// (1 === 1) && (2 === 6) //=> false
Zo simpel is het. Hier heb ik vanilla JS-objecten gebruikt, maar dit type comparator zou kunnen werken voor elkobjecttype; zelfs uw aangepaste objecten. De oplossing van Tomáš zou volledig moeten worden herwerkt om dit soort gelijkheidstests te ondersteunen
Diepe array met objecten? Geen probleem. We hebben zeer veelzijdige, generieke functies gebouwd, zodat ze in een groot aantal verschillende gebruikssituaties werken.
const xs = [{id:1}, [{id:2}]]
const ys = [{id:1}, [{id:2}]]
console.log (arrayCompare (idEqual) (xs) (ys)) //=> false
console.log (arrayDeepCompare (idEqual) (xs) (ys)) //=> true
Willekeurige vergelijking (voorbeeld)
Of wat als u een ander soort volledig willekeurige vergelijking zou willen maken? Misschien wil ik weten of elke x
groter is dan elke y
…
// gt :: Number -> Number -> Bool
const gt = x => y =>
x > y
// arrayGt :: [a] -> [a] -> Bool
const arrayGt = arrayCompare (gt)
const xs = [5,10,20]
const ys = [2,4,8]
console.log (arrayGt (xs) (ys)) //=> true
// (5 > 2) && (10 > 4) && (20 > 8) //=> true
const zs = [6,12,24]
console.log (arrayGt (xs) (zs)) //=> false
// (5 > 6) //=> false
Minder is meer
Je kunt zien dat we meer doen met minder code. Er is niets ingewikkelds aan arrayCompare
zelf en elk van de aangepaste vergelijkers die we hebben gemaakt, heeft een zeer eenvoudige implementatie.
Met gemak kunnen we precies definiëren hoe we willen dat twee arrays worden vergeleken – ondiep, diep, strikt, los, een objecteigenschap of een willekeurige berekening, of een combinatie hiervan – allemaal met behulp van één procedure , arrayCompare
. Misschien zelfs een RegExp
comparator bedenken! Ik weet hoe kinderen dol zijn op die regexp’s …
Is het de snelste? Nee. Maar dat hoeft waarschijnlijk ook niet. Als snelheid de enige maatstaf is die wordt gebruikt om de kwaliteit van onze code te meten, zou veel echt geweldige code worden weggegooid — daarom noem ik deze benadering The Practical Way. Of misschien om eerlijker te zijn, EenPraktische Manier. Deze beschrijving is geschikt voor dit antwoord, omdat ik niet zeg dat dit antwoord alleen praktisch is in vergelijking met een ander antwoord; het is objectief waar. We hebben een hoge mate van bruikbaarheid bereikt met heel weinig code waar heel gemakkelijk over te redeneren is. Geen enkele andere code kan zeggen dat we deze beschrijving niet hebben verdiend.
Maakt dat het de “juiste” oplossing voor u? Dat is klaar voor u om te beslissen. En niemand anders kan dat voor u doen; alleen jij weet wat je behoeften zijn. In bijna alle gevallen waardeerde ik rechtlijnige, praktische en veelzijdige code over slimme en snelle soort. Wat u waardeert, kan verschillen, dus kies wat voor u werkt.
Bewerken
Mijn oude antwoord was meer gericht op het ontbinden arrayEqual
in kleine procedures. Het is een interessante oefening, maar niet echt de beste (meest praktische) manier om dit probleem te benaderen. Als u geïnteresseerd bent, kunt u deze revisiegeschiedenis zien.
6, Autoriteit 6%
Het is onduidelijk wat je bedoelt met “identiek”. Zijn bijvoorbeeld de arrays a
en b
hieronder identiek (let op de geneste arrays)?
var a = ["foo", ["bar"]], b = ["foo", ["bar"]];
Hier is een geoptimaliseerde arrayvergelijkingsfunctie die de overeenkomstige elementen van elke array op zijn beurt met behulp van strikte gelijkheid vergelijkt en geen recursieve vergelijking is van arrayelementen die zelf arrays zijn, wat betekent dat voor het bovenstaande voorbeeld, arraysIdentical(a, b)
zou terugkeren false
. Het werkt in het algemene geval, welke JSON- en join()
-Based Solutions niet:
function arraysIdentical(a, b) {
var i = a.length;
if (i != b.length) return false;
while (i--) {
if (a[i] !== b[i]) return false;
}
return true;
};
7, Autoriteit 3%
Bouw het antwoord van Tomáš Zato, ik ben het ermee eens dat het gewoon door de arrays de snelste is. Bovendien (zoals anderen hebben al vermeld), moet de functie gelijken / gelijk worden genoemd, niet te vergelijken. In het licht hiervan heb ik de functie gewijzigd om de reeksen voor gelijkenis te veroveren – d.w.z. ze hebben dezelfde elementen, maar niet in orde – voor persoonlijk gebruik, en dachten dat ik het hier voor iedereen zou gooien.
Array.prototype.equals = function (array, strict) {
if (!array)
return false;
if (arguments.length == 1)
strict = true;
if (this.length != array.length)
return false;
for (var i = 0; i < this.length; i++) {
if (this[i] instanceof Array && array[i] instanceof Array) {
if (!this[i].equals(array[i], strict))
return false;
}
else if (strict && this[i] != array[i]) {
return false;
}
else if (!strict) {
return this.sort().equals(array.sort(), true);
}
}
return true;
}
Deze functie heeft een aanvullende parameter van strikte die standaard naar True is. Deze strikte parameter definieert als de arrays volledig gelijk moeten zijn in zowel de inhoud als de volgorde van die inhoud, of gewoon gewoon dezelfde inhoud bevatten.
Voorbeeld:
var arr1 = [1, 2, 3, 4];
var arr2 = [2, 1, 4, 3]; // Loosely equal to 1
var arr3 = [2, 2, 3, 4]; // Not equal to 1
var arr4 = [1, 2, 3, 4]; // Strictly equal to 1
arr1.equals(arr2); // false
arr1.equals(arr2, false); // true
arr1.equals(arr3); // false
arr1.equals(arr3, false); // false
arr1.equals(arr4); // true
arr1.equals(arr4, false); // true
Ik heb ook een snelle jsfiddle geschreven met de functie en dit voorbeeld:
http://jsfiddle.net/Roundaround/DLkxX/
Antwoord 8
Ook al heeft dit veel antwoorden, een waarvan ik denk dat ze helpen:
const newArray = [ ...new Set( [...arr1, ...arr2] ) ]
Het wordt niet vermeld in de vraag hoe de structuur van de array eruit gaat zien, dus als je zeker weet dat je geen geneste arrays of objectenin je array hebt (het is mij overkomen, daarom kwam ik tot dit antwoord) de bovenstaande code zal werken.
Wat er gebeurt, is dat we de spread-operator ( … ) gebruiken om beide arrays samen te voegen, en vervolgens Set gebruiken om duplicaten te elimineren. Als je dat eenmaal hebt, kun je hun maten vergelijken, als alle drie de arrays dezelfde grootte hebben, ben je klaar om te gaan.
Dit antwoord neegt ook de volgorde van de elementen, zoals ik al zei, de exacte situatie is mij overkomen, dus misschien kan iemand in dezelfde situatie hier terechtkomen (zoals ik deed).
Bewerken1.
Beantwoorden van de vraag van Dmitry Grinko: “Waarom heb je hier de spread-operator ( … ) gebruikt – …nieuwe set? Het werkt niet”
Denk aan deze code:
const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ new Set( [...arr1, ...arr2] ) ]
console.log(newArray)
Je krijgt
[ Set { 'a', 'b', 'c' } ]
Om met die waarde te werken, moet u enkele Set-eigenschappen gebruiken (zie https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set).
Aan de andere kant, wanneer u deze code gebruikt:
const arr1 = [ 'a', 'b' ]
const arr2 = [ 'a', 'b', 'c' ]
const newArray = [ ...new Set( [...arr1, ...arr2] ) ]
console.log(newArray)
Je krijgt
[ 'a', 'b', 'c' ]
Dat is het verschil, de eerste zou me een set geven, het zou ook werken omdat ik de grootte van die set zou kunnen krijgen, maar de laatste geeft me de array die ik nodig heb, wat directer is voor de resolutie.
Antwoord 9
Op dezelfde regels als JSON.encode is om join() te gebruiken.
function checkArrays( arrA, arrB ){
//check if lengths are different
if(arrA.length !== arrB.length) return false;
//slice so we do not effect the original
//sort makes sure they are in order
//join makes it a string so we can do a string compare
var cA = arrA.slice().sort().join(",");
var cB = arrB.slice().sort().join(",");
return cA===cB;
}
var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"]; //will return true
console.log( checkArrays(a,b) ); //true
console.log( checkArrays(a,c) ); //false
console.log( checkArrays(a,d) ); //false
console.log( checkArrays(a,e) ); //true
Het enige probleem is als je om typen geeft die door de laatste vergelijking worden getest.
Als je om typen geeft, zul je moeten herhalen.
function checkArrays( arrA, arrB ){
//check if lengths are different
if(arrA.length !== arrB.length) return false;
//slice so we do not effect the orginal
//sort makes sure they are in order
var cA = arrA.slice().sort();
var cB = arrB.slice().sort();
for(var i=0;i<cA.length;i++){
if(cA[i]!==cB[i]) return false;
}
return true;
}
var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];
console.log( checkArrays(a,b) ); //true
console.log( checkArrays(a,c) ); //false
console.log( checkArrays(a,d) ); //false
console.log( checkArrays(a,e) ); //false
Als de bestelling hetzelfde moet blijven, dan is het slechts een lus, er is geen soort nodig.
function checkArrays( arrA, arrB ){
//check if lengths are different
if(arrA.length !== arrB.length) return false;
for(var i=0;i<arrA.length;i++){
if(arrA[i]!==arrB[i]) return false;
}
return true;
}
var a = [1,2,3,4,5];
var b = [5,4,3,2,1];
var c = [1,2,3,4];
var d = [1,2,3,4,6];
var e = ["1","2","3","4","5"];
console.log( checkArrays(a,a) ); //true
console.log( checkArrays(a,b) ); //false
console.log( checkArrays(a,c) ); //false
console.log( checkArrays(a,d) ); //false
console.log( checkArrays(a,e) ); //false
10
In mijn geval vergeleken arrays bevatten alleen cijfers en snaren. Deze functie laat u zien of arrays dezelfde elementen bevatten.
function are_arrs_match(arr1, arr2){
return arr1.sort().toString() === arr2.sort().toString()
}
Laten we het testen!
arr1 = [1, 2, 3, 'nik']
arr2 = ['nik', 3, 1, 2]
arr3 = [1, 2, 5]
console.log (are_arrs_match(arr1, arr2)) //true
console.log (are_arrs_match(arr1, arr3)) //false
11
kortste
Probeer een scala aan cijfers:
a1==''+a2
12
Hier is een typert-versie:
//https://stackoverflow.com/a/16436975/2589276
export function arraysEqual<T>(a: Array<T>, b: Array<T>): boolean {
if (a === b) return true
if (a == null || b == null) return false
if (a.length != b.length) return false
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false
}
return true
}
//https://stackoverflow.com/a/16436975/2589276
export function arraysDeepEqual<T>(a: Array<T>, b: Array<T>): boolean {
return JSON.stringify(a) === JSON.stringify(b)
}
Sommige testcases voor Mocha:
it('arraysEqual', function () {
let a = [1,2]
let b = [1,2]
let c = [2,3]
let d = [2, 3]
let e = ['car','apple','banana']
let f = ['car','apple','banana']
let g = ['car','apple','banan8']
expect(arraysEqual(a, b)).to.equal(true)
expect(arraysEqual(c, d)).to.equal(true)
expect(arraysEqual(a, d)).to.equal(false)
expect(arraysEqual(e, f)).to.equal(true)
expect(arraysEqual(f, g)).to.equal(false)
})
it('arraysDeepEqual', function () {
let a = [1,2]
let b = [1,2]
let c = [2,3]
let d = [2, 3]
let e = ['car','apple','banana']
let f = ['car','apple','banana']
let g = ['car','apple','banan8']
let h = [[1,2],'apple','banan8']
let i = [[1,2],'apple','banan8']
let j = [[1,3],'apple','banan8']
expect(arraysDeepEqual(a, b)).to.equal(true)
expect(arraysDeepEqual(c, d)).to.equal(true)
expect(arraysDeepEqual(a, d)).to.equal(false)
expect(arraysDeepEqual(e, f)).to.equal(true)
expect(arraysDeepEqual(f, g)).to.equal(false)
expect(arraysDeepEqual(h, i)).to.equal(true)
expect(arraysDeepEqual(h, j)).to.equal(false)
})
Antwoord 13
Uw code zal de casus niet correct afhandelen wanneer beide arrays dezelfde elementen hebben, maar niet in dezelfde volgorde.
Bekijk mijn code met uw voorbeeld waarin twee arrays worden vergeleken waarvan de elementen getallen zijn, u kunt deze wijzigen of uitbreiden voor andere elementtypen (door .join() te gebruiken in plaats van .toString()).
var a1 = [1,2,3];
var a2 = [1,2,3];
const arraysAreEqual = a1.sort().toString()==a2.sort().toString();
// true if both arrays have same elements else false
console.log(arraysAreEqual);
Antwoord 14
Je kunt eenvoudig isEqualuit de lodash-bibliotheek gebruiken. Het is zeer efficiënt en schoon.
import {isEqual} from "lodash";
const isTwoArraysEqual = isEqual(array1, array2);
Antwoord 15
Code golfen
Er zijn tal van antwoorden die laten zien hoe u arrays efficiënt kunt vergelijken.
Hieronder is de kortstemanier om twee string- of int-arrays te vergelijken, gemeten in bytes aan code.
const a = [1, 2, 3]
const b = [1, 2, 3]
console.log("1. ", a.join() === b.join())
console.log("2. ", a.join() === [].join())
console.log("3. ", 1 + a === 1 + b)
console.log("4. ", 1 + [] === 1 + b)
Antwoord 16
Als je een testframework gebruikt zoals Mokkamet de Chai-beweringbibliotheek, u kunt diepgebruiken gelijkheid om arrays te vergelijken.
expect(a1).to.deep.equal(a2)
Dit zou alleen true moeten retourneren als de arrays gelijke elementen hebben op overeenkomstige indices.
Antwoord 17
Als het slechts twee reeksen getallen of tekenreeksen zijn, is dit een snelle éénregel
const array1 = [1, 2, 3];
const array2 = [1, 3, 4];
console.log(array1.join(',') === array2.join(',')) //false
const array3 = [1, 2, 3];
const array4 = [1, 2, 3];
console.log(array3.join(',') === array4.join(',')) //true
Antwoord 18
Er is een Fase 1-voorstel, geïntroduceerd in 2020, om de gemakkelijke vergelijking van arrays door Array.prototype.equals
toe te voegen aan de taal. Dit is hoe het zou werken, zonder bibliotheken, monkeypatching of enige andere code:
[1, 2, 3].equals([1, 2, 3]) // evaluates to true
[1, 2, undefined].equals([1, 2, 3]) // evaluates to false
[1, [2, [3, 4]]].equals([1, [2, [3, 4]]]) // evaluates to true
Het is slechts een voorstel tot nu toe – TC39 zal nu “tijd besteden aan het onderzoeken van de probleemruimte , Oplossingen en Cross-Snijproblemen “. Als het tot fase 2 maakt, heeft het een goede kans om uiteindelijk in de juiste taal te worden geïntegreerd.
19
Dit vergelijkt 2 ongesorteerde arrays:
function areEqual(a, b) {
if ( a.length != b.length) {
return false;
}
return a.filter(function(i) {
return !b.includes(i);
}).length === 0;
}
20
We kunnen dit de functionele manier doen, met behulp van every
(https://developer.mozilla.org/en/docs/web/javascript/referentie/global_objects/array/every )
function compareArrays(array1, array2) {
if (array1.length === array2.length)
return array1.every((a, index) => a === array2[index])
else
return false
}
// test
var a1 = [1,2,3];
var a2 = [1,2,3];
var a3 = ['a', 'r', 'r', 'a', 'y', '1']
var a4 = ['a', 'r', 'r', 'a', 'y', '2']
console.log(compareArrays(a1,a2)) // true
console.log(compareArrays(a1,a3)) // false
console.log(compareArrays(a3,a4)) // false
21
Hier een mogelijkheid voor ongesorteerde arrays en aangepaste vergelijking:
const array1 = [1,3,2,4,5];
const array2 = [1,3,2,4,5];
const isInArray1 = array1.every(item => array2.find(item2 => item===item2))
const isInArray2 = array2.every(item => array1.find(item2 => item===item2))
const isSameArray = array1.length === array2.length && isInArray1 && isInArray2
console.log(isSameArray); //true
22
Herer’s mijn oplossing:
/**
* Tests two data structures for equality
* @param {object} x
* @param {object} y
* @returns {boolean}
*/
var equal = function(x, y) {
if (typeof x !== typeof y) return false;
if (x instanceof Array && y instanceof Array && x.length !== y.length) return false;
if (typeof x === 'object') {
for (var p in x) if (x.hasOwnProperty(p)) {
if (typeof x[p] === 'function' && typeof y[p] === 'function') continue;
if (x[p] instanceof Array && y[p] instanceof Array && x[p].length !== y[p].length) return false;
if (typeof x[p] !== typeof y[p]) return false;
if (typeof x[p] === 'object' && typeof y[p] === 'object') { if (!equal(x[p], y[p])) return false; } else
if (x[p] !== y[p]) return false;
}
} else return x === y;
return true;
};
Werkt met elke geneste data-structuur en negeert duidelijk de methoden van objecten. Denk niet eens aan het uitbreiden van Object.Prototype met deze methode, toen ik dit eenmaal probeerde, heeft JQuery gebroken;)
Voor de meeste arrays is het nog steeds sneller dan de meeste serialisatie-oplossingen. Het is waarschijnlijk de snelste vergelijkingsmethode voor arrays van objectrecords.
23
Nog een benadering met heel weinig code (met Array Verminder en array bevat ):
arr1.length == arr2.length && arr1.reduce((a, b) => a && arr2.includes(b), true)
Als u ook de gelijkheid van de bestelling wilt vergelijken:
arr1.length == arr2.length && arr1.reduce((a, b, i) => a && arr2[i], true)
-
De
length
Controleren zorgt ervoor dat de set elementen in één array niet alleen een subset van de andere is. -
De reducer wordt gebruikt om door één array te lopen en naar elk item in een andere array te zoeken. Als een item niet wordt gevonden, retourneert de vermindering de functie
false
.- In het eerste voorbeeld wordt getest dat een element is opgenomen
- De tweede voorbeeldcontrole voor de bestelling ook
24
Een eenvoudige aanpak:
function equals(a, b) {
if ((a && !b) || (!a && b) || (!a && !b) || (a.length !== b.length)) {
return false;
}
var isDifferent = a.some(function (element, index) {
return element !== b[index];
});
return !isDifferent;
}
25
JSON.stringify(collectionNames).includes(JSON.stringify(sourceNames)) ? array.push(collection[i]) : null
Zo heb ik het gedaan.
Antwoord 26
2 arrays vergelijken:
var arr1 = [1,2,3];
var arr2 = [1,2,3];
function compare(arr1,arr2)
{
if((arr1 == arr2) && (arr1.length == arr2.length))
return true;
else
return false;
}
aanroepfunctie
var isBool = compare(arr1.sort().join(),arr2.sort().join());
Antwoord 27
Al een aantal geweldige antwoorden. Maar ik wil graag een ander idee delen dat betrouwbaar is gebleken bij het vergelijken van arrays. We kunnen twee arrays vergelijken met behulp van JSON .stringify ( ). Het maakt een string uit de array en vergelijkt dus twee verkregen strings van twee arrays voor gelijkheid
JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:1},2]) //true
JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},2]) //false
JSON.stringify([1,{a:1},2]) == JSON.stringify([1,{a:2},[3,4],2]) //false
JSON.stringify([1,{a:1},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //false
JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4],2]) //true
JSON.stringify([1,{a:2},[3,4],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false
JSON.stringify([1,{a:2},[3,4,[4]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //false
JSON.stringify([1,{a:2},[3,4,[5]],2]) == JSON.stringify([1,{a:2},[3,4,[5]],2]) //true
Antwoord 28
In a simple way uning stringify but at same time thinking in complex arrays:
**Simple arrays**:
var a = [1,2,3,4];
var b = [4,2,1,4];
JSON.stringify(a.sort()) === JSON.stringify(b.sort()) // true
**Complex arrays**:
var a = [{id:5,name:'as'},{id:2,name:'bes'}];
var b = [{id:2,name:'bes'},{id:5,name:'as'}];
JSON.stringify(a.sort(function(a,b) {return a.id - b.id})) === JSON.stringify(b.sort(function(a,b) {return a.id - b.id})) // true
**Or we can create a sort function**
function sortX(a,b) {
return a.id -b.id; //change for the necessary rules
}
JSON.stringify(a.sort(sortX)) === JSON.stringify(b.sort(sortX)) // true
Antwoord 29
Een alternatieve manier om filter- en pijlfuncties te gebruiken
arrOne.length === arrTwo.length && arrOne.filter((currVal, idx) => currVal !== arrTwo[idx]).length === 0