我有一个JavaScript数组,如:

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

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

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

当前回答

请注意:当使用Function.prototype.apply([].contat.apply([],arrays))或扩展运算符([].cantat(…arrays),以展平数组时,这两者都会导致大型数组的堆栈溢出,因为函数的每个参数都存储在堆栈上。

这里是一个以功能风格实现的堆栈安全实现,它将最重要的需求相互权衡:

可重用性可读性简洁表演

//小型、可重复使用的辅助功能:常量foldl=f=>acc=>xs=>xs.reduce(uncurry(f),acc);//aka减少常量未修正=f=>(a,b)=>f(a)(b);常量concat=xs=>y=>xs.contat(y);//使数组变平的实际函数-一个不言自明的单行:常量flatten=xs=>foldl(concat)([])(xs);//任意数组大小(直到堆爆炸:D)常量xs=[[1,2,3],[4,5,6],[7,8,9]];console.log(flatten(xs));//推导深度嵌套数组的递归解决方案现在很简单//更小型、可重复使用的辅助功能:const-map=f=>xs=>xs.map(apply(f));常量应用=f=>a=>f(a);const-isArray=Array.isArray;//导出的递归函数:const flattenr=xs=>flatten(map(x=>isArray(x)?flatnr(x):x)(xs));常量ys=[1,[2,[3,[4,[5],6,],7],8],9];控制台日志(flatnr(ys));

一旦您习惯了小箭头函数的通用形式、函数组合和更高阶的函数,这段代码读起来就像散文一样。然后,编程只包括将总是按预期工作的小构件组合在一起,因为它们不包含任何副作用。

其他回答

另一种方法是使用jQuery$.map()函数。从jQuery文档:

该函数可以返回一个值数组,该数组将被展平为完整数组。

var source = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];
var target = $.map(source, function(value) { return value; }); // ["$6", "$12", "$25", "$25", "$18", "$22", "$10"]

看起来这看起来像是一份招聘工作!

处理多层嵌套处理空数组和非数组参数没有突变不依赖现代浏览器功能

代码:

var flatten = function(toFlatten) {
  var isArray = Object.prototype.toString.call(toFlatten) === '[object Array]';

  if (isArray && toFlatten.length > 0) {
    var head = toFlatten[0];
    var tail = toFlatten.slice(1);

    return flatten(head).concat(flatten(tail));
  } else {
    return [].concat(toFlatten);
  }
};

用法:

flatten([1,[2,3],4,[[5,6],7]]);
// Result: [1, 2, 3, 4, 5, 6, 7] 

此解决方案适用于任何深度级别(指定嵌套数组结构的深度)的数组。

function flatten(obj) {
    var out = [];
    function cleanElements(input) {
        for (var i  in input){
            if (input[i]instanceof Array){
                cleanElements(input[i]);
            }
            else {
                out.push(input[i]);
            }
        }
    }
    cleanElements(obj);
    return (out);
}

这里的大多数答案都不适用于大型(例如200000个元素)阵列,即使这样,它们也很慢。

以下是最快的解决方案,它也适用于具有多层嵌套的阵列:

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,2,1,3,1,1]。

具有不同嵌套级别的数组

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

它对像这样的扁平化阵列没有任何问题。

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

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 ]