12

I am trying to write a function to flatten an array. I have part of the function working and I need help in the other half.

flatten: function(anyArray, singleLevel) {
  if (singleLevel == true) {
      flatArray = Array.prototype.concat.apply([], anyArray);
      return flatArray;
  }
  flatArray = Array.prototype.concat.apply([], anyArray);
  if (flatArray.length != anyArray.length) {
      flatArray = someObject.array.flatten(flatArray);
  }
  return flatArray;
}

if I type

.flatten([[[1],[1,2,3,[4,5],4],[2,3]]], true);

I want it to flatten only one level:

[[1],[1,2,3,[4,5],4],[2,3]]
1
  • I don't think the multi-level flat works as expected for arrays such as [[[[[1]]]]] Commented Feb 26, 2013 at 21:25

3 Answers 3

12

Modern JavaScript allows us to handle this very easily using a variety of techniques

Using Array.prototype.flat -

const arr =
  [ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
  
const flatArr =
  arr.flat(1) // 1 is default depth

console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]

Using Array.prototype.flatMap -

const arr =
  [ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
  
const flatArr =
  arr.flatMap(x => x)

console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]

Using a spread argument to Array.prototype.concat

const arr =
  [ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
  
const flatArr =
  [].concat(...arr)
  
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]


Older version of JavaScript (ECMAScript 5 and below) can use techniques like Function.prototype.apply -

var arr =
  [ [ 1 ], [ 2, 3, [ 4, 5, [ 6 ] ] ], [ 7, [ 8, 9 ] ] ]
  
var flatArr =
  Array.prototype.concat.apply([], arr)
  
console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]

Using Array.prototype.reduce -

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

var flatArr =
  arr.reduce((r, a) => r.concat(a), [])

console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]

Using a primitive for loop -

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

var flatArr =
  []
  
for (var i = 0; i < arr.length; i = i + 1)
  flatArr = flatArr.concat(arr[i])

console.log(JSON.stringify(arr))
console.log(JSON.stringify(flatArr))
// [[1],[2,3,[4,5,[6]]],[7,[8,9]]]
// [1,2,3,[4,5,[6]],7,[8,9]]

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

Comments

6

The concat array method expects one or more arrays as arguments, whose elements will be appended:

[1].concat([2, 3], [4]) // [1, 2, 3, 4]

So if you are using apply, that will flatten another level:

[].concat.apply([1], [[2], [3]]) // === [1].concat([2], [3])

So you can either use push instead of concat, or call (or just direct invocation) instead of apply to get only a single flattening level.

Comments

-1

if you use ES6/ES2015 you can use spread operator. Something like this

console.log(...[[[1],[1,2,3,[4,5],4],[2,3]]])

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.