1

I'm reading a book called Eloquent JavaScript. There's an exercise in it that requires one to flatten a heterogeneous array & after trying so long and failing to get the answer, I looked up the solution online & couldn't understand the code. I'm hoping someone will be kind enough to explain, especially for argument "flat" and how it's supposed to work. The code is below

var arrays = [[1, 2, 3], [4, 5], [6]];

console.log(arrays.reduce(function(flat, current) {
    return flat.concat(current);
}, []));
3
  • 1
    flat is the empty array init param, or the last return from the reduce callback. if you return an array, it has a concat method built-in, so this calls that method to add the current to the "stack". throw a console.log(flat, current) up top to see the breakdown. Commented Sep 22, 2015 at 17:27
  • 2
    when in doubt, check docs Array.prototype.reduce() Commented Sep 22, 2015 at 17:28
  • 1
    Read up on MDN: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Sep 22, 2015 at 17:28

5 Answers 5

2

The reduce function defined in the book is:

function reduce(array, combine, start) {
  var current = start;
  for (var i = 0; i < array.length; i++)
    current = combine(current, array[i]);
  return current;
}

and as a method of an array,

arr.reduce(combine, start);

Let's look at each part of the reduce method. The book describes it as "folding up the array, one element at a time." The first argument for reduce is the "combiner function", that accepts two arguments, the "current" value and the "next" item in the array.

Now, the initial "current" value is given as the second argument of the reduce function, and in the solution of flattening arrays, it is the empty array, []. Note that in the beginning, the "next" item in the array is the 0th item.

Quoting the book to observe: "If your array contains at least one element, you are allowed to leave off the start argument."

It may also be confusing that in the flattening solution, current is placed as the second argument to reduce, whereas in the reduce definition above, current is used to assign the cumulative, folded value. In the flattening solution, current refers to the "next" arrays item (the individual array of integers)

Now, at each step of the reduction, the "current" value plus the next array item is fed to the (anonymous) combiner, and the return value becomes the updated "current" value. That is, we consumed an element of the array and continue with the next item.

flat is merely the name given to the accumulated result. Because we wish to return a flat array, it is an appropriate name. Because an array has the concat function, the first step of the reduce function is, (pretending that I can assign the internal variables)

flat = [];  // (assignment by being the second argument to reduce)

Now, walk through the reduction as iterating over arrays, by going through the steps shown above in reduce's definition

  for (var i = 0; i < arrays.length; i++)
    flat = combine(flat, arrays[i]);

Calling combine gives [].concat([1, 2, 3]) // => [1, 2, 3]

Then,

flat = [1, 2, 3].concat([4, 5])  // => [1, 2, 3, 4, 5]

and again for the next iteration of the reduction. The final return value of the reduce function is then the final value of flat.

Sign up to request clarification or add additional context in comments.

1 Comment

I'm a little confused by this. I've learned through the book is that you can use any function as an extension, (like in C# function(this int[] Array, string foo)) So I tried this: console.log(arrays.reduce(concat, [])); However that didn't work and when I built a test: function flattenArrays(array) { var current = []; for (var i = 0; i < array.length; i++) current = concat(current, array[i]); return current; } It gave me an error "undefined function concat". When I reversed the concat and the current in the test function it worked. Why is this?
1

This would be the solution I came with with ES6 format:

const reduced = arrays.reduce((result,array) => result.concat(array),[]);

console.log(reduced);

Comments

0

I have implemented this solution and this seems to work for nested arrays as well.

function flattenArray(arr){

  for(var i=0;i<arr.length;i++){

    if(arr[i] instanceof Array){

      Array.prototype.splice.apply(arr,[i,1].concat(arr[i]))
    }

  }

  return arr;
}

Comments

0

There is an easy way to do these exercises. those functions are already built inside the javascript so you can use them easily.

But the whole joy of this exercise is to create those functions:

  1. Create reduce function. Reduce function should add all array elements. you can use a higher-order function or just a normal one. here is an example for higher-order:
function reduce(array, calculate){
  let sumOfElements = 0;
  for(let element of array){
    sumOfElements = calculate(sumOfElements, element)
  }
  return sumOfElements
} 
  1. Next step is to create a concat function. since we need to return those reduced arrays in new array we will just return them. (Warning: you must use rest parameter)
function concat(...arr){
  return arr
}
  1. And for last. you will just display it (You can use any example)

console.log(concat(reduce([1, 2, 3, 4], (a, b) => a + b), reduce([5, 6], (a, b) => a + b)))

Comments

0

The reduce method acts as a for loop iterating over each element in an array. The solution takes each array element and concatenates it to the next one. That should flatten the array.

var arr =[[1,2],[3,4],[5,6]]

function flatten(arr){

    const flat= arr.reduce((accumulator,currentValue)=>{
        return accumulator.concat(currentValue)
    })
   return flat
}

console.log(flatten(arr))

//Output 1,2,3,4,5,6

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.