[removed] Trying to flatten array only one level

2020-08-26 11:02发布

问题:

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:

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]]



回答2:

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.



回答3:

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

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