Javascript递归数组展平

IT技术 javascript arrays recursion
2021-02-23 20:38:16

我正在练习并尝试编写一个递归数组展平函数。代码在这里:

function flatten() {
    var flat = [];
    for (var i = 0; i < arguments.length; i++) {
        if (arguments[i] instanceof Array) {
            flat.push(flatten(arguments[i]));
        }
        flat.push(arguments[i]);
    }
    return flat;
}

问题是,如果我在那里传递一个数组或嵌套数组,我会收到“超出最大调用堆栈大小”错误。我究竟做错了什么?

6个回答

问题是你如何传递数组的处理,如果值是一个数组,那么你一直在调用它导致无限循环

function flatten() {
    var flat = [];
    for (var i = 0; i < arguments.length; i++) {
        if (arguments[i] instanceof Array) {
            flat.push.apply(flat, flatten.apply(this, arguments[i]));
        } else {
            flat.push(arguments[i]);
        }
    }
    return flat;
}

演示:小提琴

这是一个更现代的版本:

function flatten(items) {
  const flat = [];

  items.forEach(item => {
    if (Array.isArray(item)) {
      flat.push(...flatten(item));
    } else {
      flat.push(item);
    }
  });

  return flat;
}
这是另一个现代的: function flatten(array, accu = []) { array.forEach(a => { if(Array.isArray(a)) flatten(a, accu) else accu.push(a) }) return累积}
2021-04-23 20:38:16
@mrwnt10 我并不是要听起来讽刺,而是因为它实际上是最外层的flat变量。flat每个连续帧中的底层s 最终被返回,然后被推入最终返回的顶层flat
2021-05-07 20:38:16
为什么flat在递归调用中的声明不flatten()屏蔽最外层flat变量?
2021-05-11 20:38:16

2019 年使用ES6扁平化数组的干净方法flat()

const array = [1, 1, [2, 2], [[3, [4], 3], 2]]

// All layers
array.flat(Infinity) // [1, 1, 2, 2, 3, 4, 3, 2]

// Varying depths
array.flat() // [1, 1, 2, 2, Array(3), 2]

array.flat(2) // [1, 1, 2, 2, 3, Array(1), 3, 2]
array.flat().flat() // [1, 1, 2, 2, 3, Array(1), 3, 2]

array.flat(3) // [1, 1, 2, 2, 3, 4, 3, 2]
array.flat().flat().flat() // [1, 1, 2, 2, 3, 4, 3, 2]

Mozilla 文档

我可以使用吗- 2020 年 12 月 92%

如果项目是数组,我们只需将所有剩余的项目添加到该数组中

function flatten(array, result) {
  if (array.length === 0) {
    return result
  }
  var head = array[0]
  var rest = array.slice(1)
  if (Array.isArray(head)) {
    return flatten(head.concat(rest), result)
  }
  result.push(head)
  return flatten(rest, result)
}

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

这应该是选择的答案。它不使用任何迭代循环。
2021-05-06 20:38:16
[...arr.toString().split(",")]

使用 的toString()方法Object使用扩展运算符(...)创建一个字符串数组并将其拆分为",".

例子:

let arr =[["1","2"],[[[3]]]]; // output : ["1", "2", "3"]
这会将数字转换为字符串,并将拆分包含逗号的字符串。
2021-04-24 20:38:16

一个 Haskelesque 的方法......

function flatArray([x,...xs]){
  return x !== undefined ? [...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);

所以我认为上面的代码片段可以通过适当的缩进更容易理解;

function flatArray([x,...xs]){
  return x !== undefined ? [ ...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);