Om een array in JavaScript te dupliceren: Welke van de volgende is sneller te gebruiken?
slice
methode
var dup_array = original_array.slice();
For
lus
for(var i = 0, len = original_array.length; i < len; ++i)
dup_array[i] = original_array[i];
Ik weet dat beide manieren slechts een ondiepe kopiedoen: als original_array
verwijzingen naar objecten bevat, worden objecten niet gekloond, maar worden alleen de verwijzingen gekopieerd, en daarom hebben beide arrays verwijzingen naar dezelfde objecten.
Maar dit is niet het punt van deze vraag.
Ik vraag alleen naar snelheid.
Antwoord 1, autoriteit 100%
Er zijn minstens 6(!) manieren om een array te klonen:
- lus
- plakje
- Array.from()
- concat
- spread-operator (SNELSTE)
- kaart
A.map(function(e){return e;});
Er is een enorme BENCHMARKS-threadgeweest, met de volgende informatie:
-
voor blinkbrowsers is
slice()
de snelste methode,concat()
is iets langzamer enwhile loop
is 2,4x langzamer. -
voor andere browsers is
while loop
de snelste methode, aangezien die browsers geen interne optimalisaties hebben voorslice
enconcat
.
Dit blijft zo in juli 2016.
Hieronder staan eenvoudige scripts die u kunt kopiëren en plakken in de console van uw browser en meerdere keren kunt uitvoeren om de afbeelding te zien. Ze produceren milliseconden, lager is beter.
terwijl-lus
n = 1000*1000;
start = + new Date();
a = Array(n);
b = Array(n);
i = a.length;
while(i--) b[i] = a[i];
console.log(new Date() - start);
plakje
n = 1000*1000;
start = + new Date();
a = Array(n);
b = a.slice();
console.log(new Date() - start);
Houd er rekening mee dat deze methoden het Array-object zelf zullen klonen, de inhoud van de array wordt echter door verwijzing gekopieerd en wordt niet diep gekloond.
origAr == clonedArr //returns false
origAr[0] == clonedArr[0] //returns true
Antwoord 2, autoriteit 33%
Technisch gezien is slice
de snelste manier. Echtergaat nog sneller als u de 0
beginindex toevoegt.
myArray.slice(0);
is sneller dan
myArray.slice();
https://web.archive. org/web/20170824010701/https://jsperf.com/cloning-arrays/3
Antwoord 3, autoriteit 19%
hoe zit het met es6 way?
arr2 = [...arr1];
Antwoord 4, autoriteit 5%
Gemakkelijkste manier om een array of object diep te klonen:
var dup_array = JSON.parse(JSON.stringify(original_array))
Antwoord 5, autoriteit 4%
var cloned_array = [].concat(target_array);
Antwoord 6, autoriteit 3%
Ik heb een korte demo samengesteld: http://jsbin.com/agugo3/edit
Mijn resultaten op Internet Explorer 8 zijn 156, 782 en 750, wat aangeeft dat slice
in dit geval veel sneller is.
Antwoord 7
ECMAScript 2015-manier met de Spread
-operator:
Basisvoorbeelden:
var copyOfOldArray = [...oldArray]
var twoArraysBecomeOne = [...firstArray, ..seccondArray]
Probeer het in de browserconsole:
var oldArray = [1, 2, 3]
var copyOfOldArray = [...oldArray]
console.log(oldArray)
console.log(copyOfOldArray)
var firstArray = [5, 6, 7]
var seccondArray = ["a", "b", "c"]
var twoArraysBecomOne = [...firstArray, ...seccondArray]
console.log(twoArraysBecomOne);
Referenties
Antwoord 8
Zoals @Dan zei: “Dit antwoord veroudert snel. Gebruik benchmarksom de werkelijke situatie”, is er één specifiek antwoord van jsperf dat voor zichzelf geen antwoord heeft gehad: terwijl:
var i = a.length;
while(i--) { b[i] = a[i]; }
had 960.589 ops/sec met de nummer twee a.concat()
op 578.129 ops/sec, wat 60% is.
Dit is de nieuwste Firefox (40) 64 bit.
@aleclarson heeft een nieuwe, betrouwbaardere benchmark gemaakt.
Antwoord 9
Het hangt af van de browser. Als je kijkt in de blogpost Array.prototype.slice versus handmatige arraycreatie, er is een ruwe handleiding voor de prestaties van elk:
Resultaten:
Antwoord 10
Er is een veel schonere oplossing:
var srcArray = [1, 2, 3];
var clonedArray = srcArray.length === 1 ? [srcArray[0]] : Array.apply(this, srcArray);
De lengtecontrole is vereist, omdat de Array
-constructor zich anders gedraagt wanneer deze wordt aangeroepen met precies één argument.
Antwoord 11
Onthoud dat .slice() niet werkt voor tweedimensionale arrays. Je hebt een functie als deze nodig:
function copy(array) {
return array.map(function(arr) {
return arr.slice();
});
}
Antwoord 12
Het hangt af van de lengte van de array. Als de arraylengte <= 1.000.000 is, nemen de methoden slice
en concat
ongeveer dezelfde tijd in beslag. Maar als je een groter bereik geeft, wint de concat
-methode.
Probeer bijvoorbeeld deze code:
var original_array = [];
for(var i = 0; i < 10000000; i ++) {
original_array.push( Math.floor(Math.random() * 1000000 + 1));
}
function a1() {
var dup = [];
var start = Date.now();
dup = original_array.slice();
var end = Date.now();
console.log('slice method takes ' + (end - start) + ' ms');
}
function a2() {
var dup = [];
var start = Date.now();
dup = original_array.concat([]);
var end = Date.now();
console.log('concat method takes ' + (end - start) + ' ms');
}
function a3() {
var dup = [];
var start = Date.now();
for(var i = 0; i < original_array.length; i ++) {
dup.push(original_array[i]);
}
var end = Date.now();
console.log('for loop with push method takes ' + (end - start) + ' ms');
}
function a4() {
var dup = [];
var start = Date.now();
for(var i = 0; i < original_array.length; i ++) {
dup[i] = original_array[i];
}
var end = Date.now();
console.log('for loop with = method takes ' + (end - start) + ' ms');
}
function a5() {
var dup = new Array(original_array.length)
var start = Date.now();
for(var i = 0; i < original_array.length; i ++) {
dup.push(original_array[i]);
}
var end = Date.now();
console.log('for loop with = method and array constructor takes ' + (end - start) + ' ms');
}
a1();
a2();
a3();
a4();
a5();
Als u de lengte van original_array instelt op 1.000.000, nemen de methode slice
en concat
ongeveer dezelfde tijd in beslag (3-4 ms, afhankelijk van de willekeurige cijfers).
Als je de lengte van original_array instelt op 10.000.000, dan duurt de methode slice
meer dan 60 ms en de methode concat
meer dan 20 ms.
Antwoord 13
Benchmarktijd!
function log(data) {
document.getElementById("log").textContent += data + "\n";
}
benchmark = (() => {
time_function = function(ms, f, num) {
var z = 0;
var t = new Date().getTime();
for (z = 0;
((new Date().getTime() - t) < ms); z++)
f(num);
return (z)
}
function clone1(arr) {
return arr.slice(0);
}
function clone2(arr) {
return [...arr]
}
function clone3(arr) {
return [].concat(arr);
}
Array.prototype.clone = function() {
return this.map(e => Array.isArray(e) ? e.clone() : e);
};
function clone4(arr) {
return arr.clone();
}
function benchmark() {
function compare(a, b) {
if (a[1] > b[1]) {
return -1;
}
if (a[1] < b[1]) {
return 1;
}
return 0;
}
funcs = [clone1, clone2, clone3, clone4];
results = [];
funcs.forEach((ff) => {
console.log("Benchmarking: " + ff.name);
var s = time_function(2500, ff, Array(1024));
results.push([ff, s]);
console.log("Score: " + s);
})
return results.sort(compare);
}
return benchmark;
})()
log("Starting benchmark...\n");
res = benchmark();
console.log("Winner: " + res[0][0].name + " !!!");
count = 1;
res.forEach((r) => {
log((count++) + ". " + r[0].name + " score: " + Math.floor(10000 * r[1] / res[0][1]) / 100 + ((count == 2) ? "% *winner*" : "% speed of winner.") + " (" + Math.round(r[1] * 100) / 100 + ")");
});
log("\nWinner code:\n");
log(res[0][0].toString());
<textarea rows="50" cols="80" style="font-size: 16; resize:none; border: none;" id="log"></textarea>
Antwoord 14
In ES6 kun je eenvoudig de Spread syntaxis.
Voorbeeld:
let arr = ['a', 'b', 'c'];
let arr2 = [...arr];
Houd er rekening mee dat de spread-operator een volledig nieuwe array genereert, dus het wijzigen van de ene heeft geen invloed op de andere.
Voorbeeld:
arr2.push('d') // becomes ['a', 'b', 'c', 'd']
console.log(arr) // while arr retains its values ['a', 'b', 'c']
Antwoord 15
De snelste manier om een array van objecten te klonen is door de spread-operator te gebruiken
var clonedArray=[...originalArray]
maar de objecten in die gekloonde array zullen nog steeds naar de oude geheugenlocatie wijzen. vandaar dat verandering naar clonedArray-objecten ook de orignalArray zal veranderen.
var clonedArray = originalArray.map(({...ele}) => {return ele})
hiermee wordt niet alleen een nieuwe array gemaakt, maar worden ook de objecten gekloond.
Antwoord 16
Een eenvoudige oplossing:
original = [1,2,3]
cloned = original.map(x=>x)
Antwoord 17
const arr = ['1', '2', '3'];
// Old way
const cloneArr = arr.slice();
// ES6 way
const cloneArrES6 = [...arr];
// But problem with 3rd approach is that if you are using muti-dimensional
// array, then only first level is copied
const nums = [
[1, 2],
[10],
];
const cloneNums = [...nums];
// Let's change the first item in the first nested item in our cloned array.
cloneNums[0][0] = '8';
console.log(cloneNums);
// [ [ '8', 2 ], [ 10 ], [ 300 ] ]
// NOOooo, the original is also affected
console.log(nums);
// [ [ '8', 2 ], [ 10 ], [ 300 ] ]
Dus, om te voorkomen dat deze scenario’s gebeuren, gebruik
const arr = ['1', '2', '3'];
const cloneArr = Array.from(arr);
Antwoord 18
Er waren verschillende manieren om een array te klonen. Klonen werd in principe op twee manieren gecategoriseerd:
- Ondiepe kopie
- Diepe kopie
Ondiepe kopieën bedekken alleen het 1e niveau van de array en de rest is
verwezen. Als je een echte kopie van geneste elementen in de arrays wilt, heb je a . nodig
diepe kloon.
Voorbeeld:
const arr1 = [1,2,3,4,5,6,7]
// Normal Array (shallow copy is enough)
const arr2 = [1,2,3,[4],[[5]],6,7]
// Nested Array (Deep copy required)
Approach 1 : Using (...)Spread Operator (Shallow copy enough)
const newArray = [...arr1] // [1,2,3,4,5,6,7]
Approach 2 : Using Array builtIn Slice method (Deep copy)
const newArray = arr1.slice() // [1,2,3,4,5,6,7]
Approach 3 : Using Array builtIn Concat method (Deep a copy)
const newArray = [].concat(arr1) // [1,2,3,4,5,6,7]
Approach 4 : Using JSON.stringify/parse. (Deep a copy & fastest)
const newArray = JSON.parse(JSON.stringify(arr2));) // [1,2,3,[4],[[5]],6,7]
Approach 5: Using own recursive function or using loadash's __.cloneDeep method. (Deep copy)
Antwoord 19
Snelle manieren om een array in JavaScript op volgorde te dupliceren:
#1: array1copy = [...array1];
#2: array1copy = array1.slice(0);
#3: array1copy = array1.slice();
Als uw array-objecten enige JSON-niet-serializeerbare inhoud bevatten (functies, Number.POSITIVE_INFINITY, enz.), kunt u dit beter gebruiken
array1copy = JSON.parse(JSON.stringify(array1))
Antwoord 20
Je kunt deze code volgen. Onveranderlijke manier array kloon. Dit is de perfecte manier om arrays te klonen
const array = [1, 2, 3, 4]
const newArray = [...array]
newArray.push(6)
console.log(array)
console.log(newArray)
Antwoord 21
Als je een ECHT gekloond object/array in JS wilt met gekloonde verwijzingen van alle attributen en subobjecten:
export function clone(arr) {
return JSON.parse(JSON.stringify(arr))
}
Alle andere bewerkingen maken geen klonen, omdat ze gewoon het basisadres van het root-element wijzigen, niet van de meegeleverde objecten.
behalve dat je recursief door de object-boom doorkruist.
Voor een eenvoudige kopie zijn deze OK. Voor opslagadres Relevante bewerkingen I Suggereer ik (en in de meeste andere gevallen, omdat dit snel is!) Om te typen in tekenreeks en terug in een compleet nieuw object.