1
[].concat.apply([], arrayOfArrays)

This is how I concat multiple arrays into one (they just hold numbers).

Unfortunately, when the number of arrays is too big, I get the Maximum stack depth exceeded. How to concat more arrays than VM can push on stack?

function test (msg,f) {
    console.time(msg)
    f()
    console.timeEnd(msg)
}

function conc (a) {
    return a.concat.apply([], a)
}

function push (a) {
    var R = []
    for(var i = 0; i < a.length; i++){
        for(var j = 0; j < a[i].length; j++){
            R .push (a[i][j])
        }
    }
    return R
}

function conc2 (a) {
    var R = []
        for(var i = 0; i < a.length; i++)R.push.apply(R, a[i])
    return R
}

L = []
for (var i = 0; i< 10000; i++) {
    var S = []
    for (var j = 0; j < 70; j++) S .push (Math.round (Math.random() * 500))
    L.push(S)
}

//L = [[1,2], [3,4], [5,6], [7,8], [9,0]]
var A, B, C

test('concat', function (a,b,c) {
    A = conc(L)
})

test('push', function (a,b,c) {
    B = push(L)
})

test('concat2', function (a,b,c) {
    C = conc2(L)
})

if (A.length < 200) console.log( JSON.stringify(A), JSON.stringify(B), JSON.stringify(C)) 
console.log( A.length, B.length, C.length) 

Results are concat.apply:20ms, push:80ms, concat loop: 60 ms

apply is so much faster! But it is limited to stack size. How to overcome the stack limit retaining performance?

exebook
  • 32,014
  • 33
  • 141
  • 226
  • 1
    Use a loop instead of `apply`. It's hard to be specific without knowing more about your `arrayOfArrays` – Xotic750 Jun 04 '15 at 09:38
  • see also http://stackoverflow.com/questions/18308700/chrome-how-to-solve-maximum-call-stack-size-exceeded-errors-on-math-max-apply – georg Jun 04 '15 at 09:43
  • If using `apply` with `concat` gives you `Maximum stack depth exceeded` then that is hardly performant when a loop doesn't crash. Perhaps you can check the size of your data and if in certain limits use `apply` otherwise use a loop. – Xotic750 Jun 04 '15 at 10:17

1 Answers1

1

Assuming a basic structure of your arrayOfArrays, then something like this.

var arrayOfArrays = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8]
    ],
    result1 = [].concat.apply([], arrayOfArrays),
    result2 = arrayOfArrays.reduce(function (acc, arr) {
        return acc.concat(arr);
    }, []);

document.getElementById('out').textContent = JSON.stringify(result1, null, 2) + '\n' +JSON.stringify(result2, null, 2);
<pre id="out"></pre>
Xotic750
  • 22,914
  • 8
  • 57
  • 79