Fastest Way to Duplicate an Array in JavaScript - Slice Vs. 'For' Loop

Fastest way to duplicate an array in JavaScript - slice vs. 'for' loop

There are at least 6 (!) ways to clone an array:

  • loop
  • slice
  • Array.from()
  • concat
  • spread operator (FASTEST)
  • map A.map(function(e){return e;});

There has been a huuuge BENCHMARKS thread, providing following information:

  • for blink browsers slice() is the fastest method, concat() is a bit slower, and while loop is 2.4x slower.

  • for other browsers while loop is the fastest method, since those browsers don't have internal optimizations for slice and concat.

This remains true in Jul 2016.

Below are simple scripts that you can copy-paste into your browser's console and run several times to see the picture. They output milliseconds, lower is better.

while loop

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);

slice

n = 1000*1000;
start = + new Date();
a = Array(n);
b = a.slice();
console.log(new Date() - start);

Please note that these methods will clone the Array object itself, array contents however are copied by reference and are not deep cloned.

origAr == clonedArr //returns false
origAr[0] == clonedArr[0] //returns true

Javascript - Fastest way of copying an array portion into another

You could keep unrolling the loop for even slighter increases in performance, but it seems like this is just about as fast as you're going to get it. As Gumbo stated in a comment, try using pre-increment instead of post-increment:

var i = 0x4000>>5 + 1; // loops count
var j = 0x4000 - 1; // write start index
var k = 0x8000 - 1; // read start index
while (--i) { // loop unrolling
dst[++j]=src[++k]; dst[++j]=src[++k];
dst[++j]=src[++k]; dst[++j]=src[++k];
dst[++j]=src[++k]; dst[++j]=src[++k];
dst[++j]=src[++k]; dst[++j]=src[++k];
//8
...

What's the fastest way to loop through an array in JavaScript?

After performing this test with most modern browsers:
https://jsben.ch/wY5fo

Currently, the fastest form of loop (and in my opinion the most syntactically obvious).

A standard for-loop with length caching

    var i = 0, len = myArray.length;
while (i < len) {
// your code
i++
}

I would say, this is definitely a case where I applaud JavaScript engine developers. A runtime should be optimized for clarity, not cleverness.

A copy of an array changes the original array even with slice

You aren't changing the array, you are mutating the objects within the array. You don't want that.

const myObj = {
x:1,
y:1
};

const myArray = [myObj];
const myNewArray = [...myArray];

myNewArray[0].x = 2;
console.log(myArray[0].x); // 2!!!!!

If you are changing an object within the array and you don't want it to mutate, then do this:

const myObj = {
x:1,
y:1
};

const myArray = [myObj];

// helper function that will perform a mutation at a given position
// and ignore all other positions
const mutateObjectAtPosition = (pos,mutation) => [...myArray].map((o,i) => i === pos ? mutation(o) : o)

// at position 0, return a **new object** with x set to 2
const myNewArray = mutateObjectAtPosition(0,(o) => ({...o,x:2}));

console.log(myNewArray !== myArray); // true, different references
console.log(myNewArray[0].x); // 2
console.log(myArray[0].x); // 1

Javascript array copying, concat vs slice, which one is better?

For clarity, you should use the method that is the documented method of taking a copy of an array (or portion thereof):

var c2 = a.slice(0);

On any decent browser the performance difference will be negligible, so clarity should be the deciding factor.

loop through slices and amend into a 2D array

You can achieve the same without using extra variables

package main

import (
"fmt"
"log"
"strings"

"golang.org/x/exp/slices"
)

func main() {

var codeSlices = []string{
"# INPUTS",
"",
"input CreateUserInput {",
" username: String!",
" email: String!",
" password: String!",
"}",
"",
"input AuthUserInput {",
" user: String!",
" password: String!",
" code: String",
"}",
"",
"input RefreshTokensInput{",
" refreshToken: String!",
"}",
"",
"input VerifyEmailInput {",
" token: String!",
"}",
"",
"# OBJECTS",
"",
}

//Check for boundaries
inputStart := slices.Index(codeSlices, "# INPUTS") //Use built-in functions for the search
if inputStart == -1 {
log.Fatal("# INPUTS not found")
}

objectStart := slices.Index(codeSlices, "# OBJECTS")
if objectStart == -1 {
log.Fatal("# OBJECTS not found")
}

inputStart = 0
var inputs [][]string
for i := inputStart + 2; i < objectStart-1; i++ {
if idx := strings.Index(codeSlices[i], "{"); idx > 0 {
inputStart = i
continue
}
if idx := slices.Index(codeSlices[inputStart:], "}"); inputStart > 0 {
inputs = append(inputs, codeSlices[inputStart:i+idx])
inputStart = 0
}
}

if inputStart > 0 {
log.Fatal("Mismatch inputs")
}

fmt.Printf("%#v\n", inputs)
}

Playground

Is there a method to add and an arry of objects to the end of an array of objects without makeing a for loop?

I would use the spread syntax ...

const obj1 = [{"d": "1", "t": "1"}, {"d": "2", "t": "2"}]
const obj2 = [{"d": "3", "t": "3"}, {"d": "4", "t": "4"}]
const obj3 = [...obj1, ...obj2]

console.log(obj3)


Related Topics



Leave a reply



Submit