我有一个JavaScript数组,如:

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

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

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

当前回答

[1,[2,3],[4,[5,6]]].reduce(function(p, c) {
    return p.concat(c instanceof Array ? 
                    c.reduce(arguments.callee, []) : 
                    [c]); 
}, []);

其他回答

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

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

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

我最初想使用.reduce方法并递归调用一个函数来展平内部数组,但是当使用深度嵌套数组的深度嵌套数组时,这可能会导致堆栈溢出。使用concat也不是最好的方法,因为每次迭代都会创建数组的新浅层副本。我们可以做的是:

const flatten = arr => {
    for(let i = 0; i < arr.length;) {
        const val = arr[i];
        if(Array.isArray(val)) {
            arr.splice(i, 1, ...val);
        } else {
            i ++;
        }
    }
    return arr;
}

我们没有通过concat创建新数组,也没有递归调用任何函数。

http://jsbin.com/firiru/4/edit?js安慰

这并不难,只需遍历数组并合并它们:

var result = [], input = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"]];

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

我提出了两个没有递归的简短解决方案。从计算复杂性的角度来看,它们不是最优的,但在一般情况下工作良好:

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