1

I am trying to solve this problem with recursion because I want to make my life worse. I am taking an array of arrays and returning one array with all of the values. It is so close to working but the new array I am pushing to keeps reseting after every recursion. Can I get some advice?

var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]]

const flatten = function (arr) {
  let output = [];

  arr.map(element => {
    if (Array.isArray(element)) {
      console.log('Is Array ---> ', element)
      flatten(element);
    } else {
      console.log('Output ----->', output)
      console.log('Else     --->', element)
      output.push(element);
    }

  });

  return output;

};

console.log('Retrun ----->', flatten(myArray)); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
3
  • Inside your map, you call flatten but you never use the result. Also, using a map but not using its return value can be misleading. forEach may be more appropriate Commented Nov 30, 2019 at 21:37
  • It is not what you are currently asking but just in case if you are not aware, there is such function : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Nov 30, 2019 at 21:43
  • Yes thanks! I looked this one up but I wanted to figure it out with recursion. Commented Nov 30, 2019 at 21:55

5 Answers 5

1

You should push the results of calling flatten(element) using the spread syntax:

output.push(...flatten(element));

Note: you should also replace the map call with Array.forEach(), since you don't use the returned array.

Example:

const flatten = function(arr) {
  const output = [];

  arr.forEach(element => {
    if (Array.isArray(element)) {
      output.push(...flatten(element));
    } else {
      output.push(element);
    }

  });

  return output;

};

var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]]


console.log(flatten(myArray)); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

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

2 Comments

Thanks! I have not come across the ... before. I had been using forEach and then switched to .map() trying anything to figure it out. Appreciate the help!
The ... are called the spread syntax.
1

If your nested arrays can't have nested arrays themselves there should be no need for recursion:

Array.prototype.flatMap gives you a simple way to flatten such arrays:

The flatMap() method first maps each element using a mapping function, then flattens the result into a new array. It is identical to a map() followed by a flat() of depth 1, but flatMap() is often quite useful, as merging both into one method is slightly more efficient.

Example:

[[1, 2],[3, 4, 5], [6, 7, 8, 9]].flatMap(xs => xs);
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]

And in case you have deeply nested arrays such as

[[1, 2, [3, 4, 5, [6, 7, 8, 9]]]]

Then a recursive flatMap is still the best option IMHO:

const flatten = xs =>
  xs.flatMap(x =>
    Array.isArray(x)
      ? flatten(x)
      : x);

flatten([[1, 2, [3, 4, 5, [6, 7, 8, 9]]]]);
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]

Of course this is all obsolete with Array.prototype.flat which can unnest deeply nested arrays:

The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.

If you don't know the depth just set it to Infinity:

[[1, 2, [3, 4, 5, [6, 7, 8, 9]]]].flat(Infinity);
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]

However it's worth noting that flat isn't supported across most modern browsers yet. If you can afford Babel in your project then there isn't much reason not to use it.


While you can build your own recursive function, it is also worth considering the native options the language has to offer.

Comments

0

I would do like this

var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]]
const flatten = (element, acc = []) => {
   if (Array.isArray(element)) {
      element.forEach(subelement => {
         flatten(subelement, acc)
      })
   } else {
      acc.push(element)
   }
   return acc
}
console.log(flatten(myArray))

Comments

0

var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]]

function flatten (arr) {
  return arr.reduce((acc, element) => {
    if (Array.isArray(element)) return [...acc, ...flatten(element)];
    acc.push(element);
    return acc;
  }, []);
}

console.log(flatten(myArray))

Comments

0

If you want it to do without using any 'magic':

function flatten(input,output){
  if(!output)
    output=[];
  if(!Array.isArray(input))
    output.push(input);
  else
    for(var i=0;i<input.length;i++)
      flatten(input[i],output);
  return output;
}

var test = [[1, 2],[3, 4, 5], 6, [[7, 8], 9]];
console.log(flatten(test).join());

I think this would be the classic, school-level recursive approach.

The particular issue in your code is the recursive call: flatten(element);. The function does not get the partial result, output (as in the code above, there is an 'optional' argument which is initialized to [] when it is missing), and whatever it returns does not get appended to the existing output either.

Any of the two would work:

var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]]

const flatten = function (arr, output) { // added output
  if(!output)                            // initializing if missing
    output = [];

  arr.map(element => {
    if (Array.isArray(element)) {
      console.log('Is Array ---> ', element.join())
      flatten(element, output);          // added output
    } else {
      console.log('Output ----->', output.join())
      console.log('Else     --->', element)
      output.push(element);
    }

  });

  return output;

};

console.log('Return ----->', flatten(myArray).join()); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

(Added some .join()s too, so the log is horizontal)

Or the second fix:

var myArray = [[1, 2],[3, 4, 5], [6, 7, 8, 9]]

const flatten = function (arr) {
  let output = [];

  arr.map(element => {
    if (Array.isArray(element)) {
      console.log('Is Array ---> ', element.join())
      output = output.concat(flatten(element));     // concatenate with result
    } else {
      console.log('Output ----->', output.join())
      console.log('Else     --->', element)
      output.push(element);
    }

  });

  return output;

};

console.log('Return ----->', flatten(myArray).join()); //[ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

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.