合并/展平数组

我有一个像这样的JavaScript数组:

[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]

我将如何将单独的内部数组合并为一个类似的数组:

["$6", "$12", "$25", ...]
宝儿猪猪西门2020/03/10 00:58:41

just the best solution without lodash

let flatten = arr => [].concat.apply([], arr.map(item => Array.isArray(item) ? flatten(item) : item))
Eva2020/03/10 00:58:41

I propose two short solutions without recursion. They are not optimal from a computational complexity point of view, but work fine in average cases:

let a = [1, [2, 3], [[4], 5, 6], 7, 8, [9, [[10]]]];

// Solution #1
while (a.find(x => Array.isArray(x)))
    a = a.reduce((x, y) => x.concat(y), []);

// Solution #2
let i = a.findIndex(x => Array.isArray(x));
while (i > -1)
{
    a.splice(i, 1, ...a[i]);
    i = a.findIndex(x => Array.isArray(x));
}
Mandy小卤蛋凯2020/03/10 00:58:41

I have done it using recursion and closures

function flatten(arr) {

  var temp = [];

  function recursiveFlatten(arr) { 
    for(var i = 0; i < arr.length; i++) {
      if(Array.isArray(arr[i])) {
        recursiveFlatten(arr[i]);
      } else {
        temp.push(arr[i]);
      }
    }
  }
  recursiveFlatten(arr);
  return temp;
}
MonsterKK梅2020/03/10 00:58:41

I recommend a space-efficient generator function:

function* flatten(arr) {
  if (!Array.isArray(arr)) yield arr;
  else for (let el of arr) yield* flatten(el);
}

// Example:
console.log(...flatten([1,[2,[3,[4]]]])); // 1 2 3 4

If desired, create an array of flattened values as follows:

let flattened = [...flatten([1,[2,[3,[4]]]])]; // [1, 2, 3, 4]
DavaidTony宝儿2020/03/10 00:58:41

You can use Array.flat() with Infinity for any depth of nested array.

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

let flatten = arr.flat(Infinity)

console.log(flatten)

check here for browser compatibility

Eva梅村村2020/03/10 00:58:41

A Haskellesque approach

function flatArray([x,...xs]){
  return x ? [...Array.isArray(x) ? flatArray(x) : [x], ...flatArray(xs)] : [];
}

var na = [[1,2],[3,[4,5]],[6,7,[[[8],9]]],10];
    fa = flatArray(na);
console.log(fa);

hide on2020/03/10 00:58:40
const common = arr.reduce((a, b) => [...a, ...b], [])
飞云Tom小宇宙2020/03/10 00:58:40

要展平单元素数组的数组,无需导入库,简单的循环既是最简单也是最有效的解决方案:

for (var i = 0; i < a.length; i++) {
  a[i] = a[i][0];
}

致拒绝投票的人:请阅读问题,不要拒绝投票,因为它不适合您的非常不同的问题。对于提出的问题,此解决方案既最快又最简单。

小小卡卡西小卤蛋2020/03/10 00:58:40

您可以使用Underscore

var x = [[1], [2], [3, 4]];

_.flatten(x); // => [1, 2, 3, 4]
前端逆天前端2020/03/10 00:58:40

功能样式的另一个ECMAScript 6解决方案:

声明功能:

const flatten = arr => arr.reduce(
  (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);

并使用它:

flatten( [1, [2,3], [4,[5,[6]]]] ) // -> [1,2,3,4,5,6]

 const flatten = arr => arr.reduce(
         (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
       );


console.log( flatten([1, [2,3], [4,[5],[6,[7,8,9],10],11],[12],13]) )

还应考虑在现代浏览器的最新版本中可用的本机函数Array.prototype.flat()(ES6的建议)。感谢@(КонстантинВан)和@(Mark Amery)在评论中提到了它。

flat函数有一个参数,指定预期的数组嵌套深度,1默认情况下等于

[1, 2, [3, 4]].flat();                  // -> [1, 2, 3, 4]

[1, 2, [3, 4, [5, 6]]].flat();          // -> [1, 2, 3, 4, [5, 6]]

[1, 2, [3, 4, [5, 6]]].flat(2);         // -> [1, 2, 3, 4, 5, 6]

[1, 2, [3, 4, [5, 6]]].flat(Infinity);  // -> [1, 2, 3, 4, 5, 6]

let arr = [1, 2, [3, 4]];

console.log( arr.flat() );

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

console.log( arr.flat() );
console.log( arr.flat(1) );
console.log( arr.flat(2) );
console.log( arr.flat(Infinity) );

十三JinJin乐2020/03/10 00:58:40

更新:事实证明,该解决方案不适用于大型阵列。如果您正在寻找更好,更快的解决方案,请查看此答案


function flatten(arr) {
  return [].concat(...arr)
}

只是简单地扩展arr并将其作为参数传递给concat(),它将所有数组合并为一个。等同于[].concat.apply([], arr)

您也可以尝试以下方法进行深展平:

function deepFlatten(arr) {
  return flatten(           // return shalowly flattened array
    arr.map(x=>             // with each x in array
      Array.isArray(x)      // is x an array?
        ? deepFlatten(x)    // if yes, return deeply flattened x
        : x                 // if no, return just x
    )
  )
}

参见有关JSBin的演示

此答案中使用的ECMAScript 6元素的参考:


旁注:find()并非所有浏览器都支持诸如和箭头功能之类的方法,但这并不意味着您现在无法使用这些功能。只需使用Babel-它将ES6代码转换为ES5。

Davaid阳光小卤蛋2020/03/10 00:58:40

那使用reduce(callback[, initialValue])方法呢JavaScript 1.8

list.reduce((p,n) => p.concat(n),[]);

会做的工作。

逆天前端2020/03/10 00:58:40

对于更一般情况的解决方案,当您的数组中可能包含一些非数组元素时。

function flattenArrayOfArrays(a, r){
    if(!r){ r = []}
    for(var i=0; i<a.length; i++){
        if(a[i].constructor == Array){
            r.concat(flattenArrayOfArrays(a[i], r));
        }else{
            r.push(a[i]);
        }
    }
    return r;
}
小胖前端逆天2020/03/10 00:58:40

最好通过javascript reduce函数来完成。

var arrays = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];

arrays = arrays.reduce(function(a, b){
     return a.concat(b);
}, []);

或者,使用ES2015:

arrays = arrays.reduce((a, b) => a.concat(b), []);

js小提琴

Mozilla文档

Tony西门古一2020/03/10 00:58:40

这里的大多数答案不适用于巨大的数组(例如20万个元素),即使是这样,它们的速度也很慢。polkovnikov.ph的答案具有最佳性能,但不适用于深度展平。

这是最快的解决方案,它也适用于具有多层嵌套的数组

const flatten = function(arr, result = []) {
  for (let i = 0, length = arr.length; i < length; i++) {
    const value = arr[i];
    if (Array.isArray(value)) {
      flatten(value, result);
    } else {
      result.push(value);
    }
  }
  return result;
};

例子

巨大的数组

flatten(Array(200000).fill([1]));

它可以处理巨大的数组。在我的机器上,此代码大约需要14毫秒才能执行。

嵌套数组

flatten(Array(2).fill(Array(2).fill(Array(2).fill([1]))));

它适用于嵌套数组。此代码产生[1, 1, 1, 1, 1, 1, 1, 1]

具有不同嵌套级别的数组

flatten([1, [1], [[1]]]);

展平像这样的数组没有任何问题。

樱Itachi2020/03/10 00:58:40

有一个令人困惑的隐藏方法,该方法构造了一个新的数组而不改变原始数组:

var oldArray = [[1],[2,3],[4]];
var newArray = Array.prototype.concat.apply([], oldArray);
console.log(newArray); // [ 1, 2, 3, 4 ]

达蒙神奇2020/03/10 00:58:40

这是一个简短的函数,它使用一些较新的JavaScript数组方法来展平n维数组。

function flatten(arr) {
  return arr.reduce(function (flat, toFlatten) {
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
  }, []);
}

用法:

flatten([[1, 2, 3], [4, 5]]); // [1, 2, 3, 4, 5]
flatten([[[1, [1.1]], 2, 3], [4, 5]]); // [1, 1.1, 2, 3, 4, 5]
斯丁理查德2020/03/10 00:58:40

您可以使用concat合并数组:

var arrays = [
  ["$6"],
  ["$12"],
  ["$25"],
  ["$25"],
  ["$18"],
  ["$22"],
  ["$10"]
];
var merged = [].concat.apply([], arrays);

console.log(merged);

使用applyof方法concat将仅将第二个参数作为数组,因此最后一行与此相同:

var merged2 = [].concat(["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]);

Array.prototype.flat()您还可以使用一种实验方法(尚不是ECMAScript标准的一部分)来展平数组,尽管该方法仅在从版本11开始的Node.js中可用,而在Edge中完全不可用

const arrays = [
      ["$6"],
      ["$12"],
      ["$25"],
      ["$25"],
      ["$18"],
      ["$22"],
      ["$10"]
    ];
const merge3 = arrays.flat(1); //The depth level specifying how deep a nested array structure should be flattened. Defaults to 1.
console.log(merge3);