无递归展平多个嵌套数组的数组-javascript

无递归展平多个嵌套数组的数组-javascript,javascript,arrays,flatten,Javascript,Arrays,Flatten,也许这是一个愚蠢的问题,但我无法意识到,在没有递归的情况下,是否有可能展平多维数组 我用递归编写了一个解决方案: function transform (arr) { var result = []; arr.forEach(flatten) function flatten (el) { if (Array.isArray(el)) { return el.forEach(flatten); } return result.pus

也许这是一个愚蠢的问题,但我无法意识到,在没有递归的情况下,是否有可能展平多维数组

我用递归编写了一个解决方案:

function transform (arr) {
   var result = [];
   arr.forEach(flatten)
   function flatten (el) {
     if (Array.isArray(el)) {
        return el.forEach(flatten);
     }
     return result.push(el);
   }
   return result;
}
要展平的阵列示例:

[1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10]
和执行:

var a = [1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10];
var r = transform(r);
console.log(r); // [1, {a: [2, 3]}, 4, 5, 6, 7, 8, 9, 10]

谢谢

您必须通过其他方式管理状态

在这里,我使用一个数组。它让我们能够跟踪我们在做什么的总体计划中所处的位置。我觉得我做这件事相当不吸引人,但工作已经完成了

function transform(arr){
    var state = [];
    var i = 0,
        a = arr;
    var result = [];
    while(true){
        var val = a[i];
        if(Array.isArray(val)){
            state.push({i: i, a: a});
            a = val;
            i = -1;
        } else if (val !== undefined) {
            result.push(val)   
        }
        if(i++ >= a.length - 1){
            if(state.length > 0)
            {
                var s = state.pop();
                a = s.a;
                i = s.i + 1;
            } else {
                break;   
            }
        }
    }
    return result;
}

var a = [1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10];
console.log(a); // Chrome Outputs: [1, Object, 4, Array[2], Array[3], 10]
var r = transform(a);
console.log(r); // Chrome Outputs: [1, Object, 4, 5, 6, 7, 8, 9, 10]

您可以使用堆栈。发现嵌套数组时,只需将其替换为其项即可

函数展平(arr){
var结果=[];
var stack=arr,第一个;
while(stack.length>0){
第一个=堆栈[0];
if(Array.isArray(第一个)){
//将嵌套数组替换为其项
Array.prototype.splice.apply(堆栈[0,1].concat(第一个));
}否则{
结果:推(第一);
//删除第一项
叠层拼接(0,1);
}
}
返回结果;
}

这是一个使用两个阵列展平另一个阵列的方案

基本上,一个数组保留某个级别的计数,另一个数组保留对该级别的数组的引用

与其他两种解决方案相比,它的主要优点是只使用Array#push,而没有其他的数组变异方法

函数变换(数组){
var结果=[],
级别=0,
reference=[array],
计数器=[0];
而(级别>=0){
if(计数器[level]>=参考[level].length){
级别--;
继续;
}
if(Array.isArray(参考[级别][计数器[级别]])){
参考[级别+1]=参考[级别][计数器[级别]]
计数器[电平]+;
级别++;
计数器[电平]=0;
继续;
}
结果.推(参考[水平][计数器[水平]]);
计数器[电平]+;
}
返回结果;
}
变量a=[1,{a:[2,3]},4,[5,[6]],[7],8,9],10],
r=变换(a);

控制台日志(r)我在采访中遇到了完全相同的问题,并提出了以下解决方案:

function flattenNonRecursion(arr) {
  const res = arr.slice();
  let i = 0;

  while (i < res.length) {
    if (Array.isArray(res[i])) {
      res.splice(i, 1, ...res[i]);
    }
    else {
      i++;
    }
  }

  return res;
}

console.log(flattenNonRecursion([1, {a: [2, 3]}, 4, [5, [6]], [[7], 8, 9], 10]));
// [1, {a: [2, 3]}, 4, 5, 6, 7, 8, 9, 10]
函数非递归(arr){
常数res=阵列切片();
设i=0;
而(i

所以,主要的想法是,我们正在通过数组前进,如果我们遇到一个数组,我们将用它的内容替换它,并继续前进。。。这个解决方案的复杂性是O(n)。

我已经将@Misha的解决方案简化了一点:

function flatten(array) {
  var result = []; 
  var stack = array
  var item;

  while (stack.length) {
    item = stack.shift();
    if (Array.isArray(item)) [].unshift.apply(stack, item);
    else result.push(item);
  }

  return result;
}
这里是O(N)解,其中N是平坦数组中的项数,而不改变输入数组

当我们使用堆栈时,使用pop和push对我来说似乎更自然。此解决方案不使用非常昂贵的拼接、取消移位、移位和其他就地阵列突变方法

使用ES6扩展运算符(不是必须的)可以替换为
apply

function flat(input) {
  const stack = [...input];
  const res = [];
  while (stack.length) {
    // pop value from stack
    const next = stack.pop();
    if (Array.isArray(next)) {
      // push back array items, won't modify the original input
      stack.push(...next);
    } else {
      res.push(next);
    }
  }
  return res.reverse();
}
我们可以使用JS数组方法来实现这一点,从2019年5月起,除IE之外的大多数浏览器都支持JS数组方法

语法 深度:可选

指定嵌套数组结构应展平的深度级别。默认值为1


展平嵌套数组 一级深度:
const arr1=[1,2,3,4]]
常数flattarr=arr1.flat()
console.log(flattarr)

//[1,2,3,4]
为什么不使用递归?@JoeEnos更多的是关于自我教育和好奇心。只使用数组很容易,但不包括对象sure@juvian这有多容易?使用
[].concat.apply([],arr)对多个嵌套不起作用:/
vara=[1,4,5,6]]、[5,6]、[7]]、8,9,10];console.log(a.toString().split(‘,’)
第一个
用于什么?我建议您在else子句中只需要这一行:
result.push(stack.splice(0,1)[0])
从堆栈中删除第一项并将其推送到结果数组中。干杯这个解决方案比公认的更干净,谢谢!我喜欢这种方法
var newArray = arr.flat([depth]);