合并/展平一个数组

IT技术 javascript arrays multidimensional-array frontend flatten
2021-01-02 00:36:34

我有一个 JavaScript 数组,如:

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

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

["$6", "$12", "$25", ...]
6个回答

您可以使用concat合并数组:

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

console.log(merged);

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

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

还有Array.prototype.flat()一种方法(在 ES2019 中引入)可用于展平数组,尽管它仅在 Node.js 版本 11 开始可用,而在 Internet Explorer 中根本不可用

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);
    

进一步@Sean 的评论:ES6 语法使这个超级简洁: var merged = [].concat(...arrays)
2021-02-09 00:36:34
或者Array.prototype.concat.apply([], arrays)
2021-02-11 00:36:34
注意:这个答案只会压平一层深。对于递归展平,请参阅@Trindaz 的答案。
2021-02-13 00:36:34
var merged = [].concat.apply([], arrays);似乎可以很好地将其放在一条线上。编辑:正如尼基塔的回答已经显示的那样。
2021-02-19 00:36:34
请注意,concat不会修改源数组,因此merged调用 后数组将保持为空concat最好这样说:merged = merged.concat.apply(merged, arrays);
2021-02-26 00:36:34

这是一个简短的函数,它使用一些较新的 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]
为什么有一个空数组作为参数传递?没有它代码就会中断,但它有什么作用呢?
2021-02-14 00:36:34
@ayjay,它是reduce 函数的起始累加器值,mdn称之为初始值。在这种情况下,它是flat在第一次调用匿名函数时传递给 的值reduce如果未指定,则第一次调用reduce将数组中的第一个值绑定到flat,这最终会导致在两个示例中都1被绑定到flat1.concat不是函数。
2021-02-26 00:36:34
对@TsvetomirTsonev 和 Noah 的任意嵌套解决方案的评论: const flatten = (arr) => arr.reduce((flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next), []);
2021-02-26 00:36:34
或者以更短、更性感的形式: const flatten = (arr) => arr.reduce((flat, next) => flat.concat(next), []);
2021-03-01 00:36:34
此解决方案的内存使用情况是什么?看起来它在尾递归期间创建了很多中间数组....
2021-03-05 00:36:34

有一种令人困惑的隐藏方法,它在不改变原始数组的情况下构造一个新数组:

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

@amoebe[[1],[2,3],[4]]结果就是你的回答@Nikita 给出的解决方案对于 CoffeeScript 和 JS 都是正确的。
2021-02-07 00:36:34
在 CoffeeScript 中,这是 [].concat([[1],[2,3],[4]]...)
2021-02-12 00:36:34
我想我也发现了你的错误。这些...是实际的代码,而不是一些省略号。
2021-02-25 00:36:34
啊,我发现了你的错误。您的符号中有一对额外的方括号,应该是[].concat([1],[2,3],[4],...).
2021-03-04 00:36:34
使用库函数并不意味着没有必要的“混乱”。只是混乱隐藏在图书馆内。显然,使用库比滚动你自己的函数要好,但声称这种技术减少了“势在必行的混乱”是非常愚蠢的。
2021-03-04 00:36:34

最好通过 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 文档

由于您使用 ES6,您还可以使用spread-operator 作为 array literalarrays.reduce((flatten, arr) => [...flatten, ...arr])
2021-02-16 00:36:34
reduce 的问题在于数组不能为空,因此您需要添加额外的验证。
2021-02-17 00:36:34
@calbertts 只需传递初始值[],无需进一步验证。
2021-02-20 00:36:34
@JohnS 实际上减少了每回合连接单个(数组)值的馈送。证明?取出reduce() 看看它是否有效。reduce() 这里是 Function.prototype.apply() 的替代方案
2021-03-03 00:36:34
我也会使用 reduce ,但我从这个片段中学到的一件有趣的事情是,大多数时候你不需要传递一个 initialValue :)
2021-03-09 00:36:34

有一种称为flat的新本机方法可以准确地执行此操作。

(截至 2019 年底,flat现已在 ECMA 2019 标准中发布,并且core-js@3(babel 的库)将其包含在他们的 polyfill库中

const arr1 = [1, 2, [3, 4]];
arr1.flat(); 
// [1, 2, 3, 4]

const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

// Flatten 2 levels deep
const arr3 = [2, 2, 5, [5, [5, [6]], 7]];
arr3.flat(2);
// [2, 2, 5, 5, 5, [6], 7];

// Flatten all levels
const arr4 = [2, 2, 5, [5, [5, [6]], 7]];
arr4.flat(Infinity);
// [2, 2, 5, 5, 5, 6, 7];
很遗憾,这甚至不在答案的第一页上。此功能在 Chrome 69 和 Firefox 62(以及用于后端工作的 Node 11)中可用
2021-02-20 00:36:34
我想现在我们可以考虑这个..因为现在它是标准(2019)的一部分..我们可以重新审视一下这个的性能部分吗?
2021-02-22 00:36:34
似乎任何微软浏览器都不支持它(至少在我写这篇评论的时候)
2021-02-26 00:36:34
-1; 不,这不是ECMAScript 2018 的一部分它仍然只是一个尚未符合任何 ECMAScript 规范的提案。
2021-02-28 00:36:34