我有一个JavaScript数组,如:

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

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

["$6", "$12", "$25", ...]

当前回答

我已经使用递归和闭包完成了

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

其他回答

有一个新的本地方法叫做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];

我有一个简单的解决方案,不用在特殊的js函数中使用。(如减少等)

const input = [[0, 1], [2, 3], [4, 5]]
let flattened=[];

for (let i=0; i<input.length; ++i) {
    let current = input[i];
    for (let j=0; j<current.length; ++j)
        flattened.push(current[j]);
}
const flatten = array => array.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []); 

根据请求,分解一行基本上就是这样。

function flatten(array) {
  // reduce traverses the array and we return the result
  return array.reduce(function(acc, b) {
     // if is an array we use recursion to perform the same operations over the array we found 
     // else we just concat the element to the accumulator
     return acc.concat( Array.isArray(b) ? flatten(b) : b);
  }, []); // we initialize the accumulator on an empty array to collect all the elements
}

泛型过程意味着我们不必在每次需要利用特定行为时重写复杂性。

concatMap(或flatMap)正是我们在这种情况下需要的。

//凹面::([a],[a])->[a]常量concat=(xs,ys)=>xs.concat(系统)//concatMap::(a->[b])->[a]->[b】常量concatMap=f=>xs=>xs.map(f).reduce(concat,[])//id::a->a常量id=x=>x(x)//展平::[[a]]->[a]常量展平=concatMap(id)//您的示例数据常量数据=[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]console.log(展平(数据))

远见

是的,你猜对了,它只会使一个层次变平,这正是它应该工作的方式

想象一下这样的数据集

//玩家::(字符串,数字)->玩家常量玩家=(姓名,号码)=>[姓名、编号]//team::(.Player)->团队const团队=(…玩家)=>玩家//游戏::(团队,团队)->游戏常量游戏=(teamA,teamB)=>[团队A,团队B]//样本数据常量团队A=团队(球员('ob',5),球员('lice',6))常量组B=团队(球员(“恶心”,4),球员(“朱利安”,2))常量游戏=游戏(A队、B队)console.log(游戏)//[[鲍勃,5],[爱丽丝,6],//[['ricky',4],['julian',2]]]

好的,现在假设我们要打印一份名册,显示所有将参加比赛的球员…

const gamePlayers = game =>
  flatten (game)

gamePlayers (game)
// => [ [ 'bob', 5 ], [ 'alice', 6 ], [ 'ricky', 4 ], [ 'julian', 2 ] ]

如果我们的展平过程也展平了嵌套数组,我们最终会得到这个垃圾结果…

const gamePlayers = game =>
  badGenericFlatten(game)

gamePlayers (game)
// => [ 'bob', 5, 'alice', 6, 'ricky', 4, 'julian', 2 ]

滚得很深,宝贝

这并不是说有时候你也不想压平嵌套的数组——只是这不应该是默认行为。

我们可以轻松地制作一个deepFlatten程序…

//凹面::([a],[a])->[a]常量concat=(xs,ys)=>xs.concat(系统)//concatMap::(a->[b])->[a]->[b】常量concatMap=f=>xs=>xs.map(f).reduce(concat,[])//id::a->a常量id=x=>x(x)//展平::[[a]]->[a]常量展平=concatMap(id)//deepFlatten::[[a]]->[a]恒定深度展平=凹面贴图(x=>Array.isArray(x)?深度展平(x):x)//您的示例数据常量数据=[0, [1, [2, [3, [4, 5], 6]]], [7, [8]], 9]console.log(展平(数据))// [ 0, 1, [ 2, [ 3, [ 4, 5 ], 6 ] ], 7, [ 8 ], 9 ]console.log(deepFlatten(数据))// [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

那里现在,每个作业都有一个工具——一个用于挤压一层嵌套、展平,另一个用于清除所有嵌套深度展平。

如果你不喜欢deepFlatten这个名字,也许你可以称之为毁灭或核武器。


不要重复两次!

当然,上面的实现是聪明和简洁的,但是使用.map后跟.reduce的调用意味着我们实际上要做的迭代超过了需要

使用我称之为mapReduce的可靠组合器,可以帮助将迭代保持在最小值;它采用一个映射函数m::a->b,一个归约函数r::(b,a)->b,并返回一个新的归约函数-这个组合子是换能器的核心;如果你感兴趣,我已经写了其他关于他们的答案

//mapReduce=(a->b,(b,a)->b,(a,b)->b)常量mapReduce=(m,r)=>(加速度,x)=>r(加速度,m(x))//concatMap::(a->[b])->[a]->[b】常量concatMap=f=>xs=>xs.reduce(mapReduce(f,concat),[])//凹面::([a],[a])->[a]常量concat=(xs,ys)=>xs.concat(系统)//id::a->a常量id=x=>x(x)//展平::[[a]]->[a]常量展平=concatMap(id)//deepFlatten::[[a]]->[a]恒定深度展平=凹面贴图(x=>Array.isArray(x)?深度展平(x):x)//您的示例数据常量数据=[ [ [ 1, 2 ],[ 3, 4 ] ],[ [ 5, 6 ],[ 7, 8 ] ] ]console.log(展平(数据))// [ [ 1. 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ]console.log(deepFlatten(数据))// [ 1, 2, 3, 4, 5, 6, 7, 8 ]

下面是现代浏览器的另一个深层次扁平化:

function flatten(xs) {
  xs = Array.prototype.concat.apply([], xs);
  return xs.some(Array.isArray) ? flatten(xs) : xs;
};