javascriptarraysfunctionfunction.prototype

flattening an array: where does the 0 come from?


This challenge is to flatten an array without defining any new functions:

// challenge
const arr = [1, [2]]
const flattened = arr.reduce(/*your code here, no function expressions or declarations allowed*/, [])
console.log(flattened) // expected: [1, 2]

My solution doesn't work, but what really bugs me is that I have no idea where the 0 is coming from:

// Solution 1
const arr = [1, [2]]
const flattened = arr.reduce(Function.prototype.call.bind(Array.prototype.concat), [])
console.log(flattened) // unexpected result: [1, 0, 1, [1], 2, 1, 1, [1]]

I'd expected the code to behave like the follow, which works as expected:

// Solution 2
const arr = [1, [2]]
const flattenReducer = (x, y) => Function.prototype.call.bind(Array.prototype.concat)(x, y)
const flattened = arr.reduce(flattenReducer, [])
console.log(flattened) // logs the expected result: [1, 2]

I tested in Node, Chrome, and Firefox and got the same results.

So where is the 0 coming from and why do Solution 1 and Solution 2 produce different values for flattened?


Solution

  • reduce's callback doesn't only have two arguments. In fact it has four: accumulator, current value, index, and the original array.

    Your solution #1 is equivalent to

    arr.reduce(function (x, y, z, a) {
        return Function.prototype.call.bind(Array.prototype.concat)(x, y, z, a);
    }, []);
    

    or equivalently

    arr.reduce(function (x, y, z, a) {
        return x.concat(y, z, a);
    }, []);
    

    which is wrong.

    Also note that both of your solutions doesn't actually flatten arrays with more than two dimensions.