用于递归展平结果的 JS 数组串联

Posted

技术标签:

【中文标题】用于递归展平结果的 JS 数组串联【英文标题】:JS array concatenation for results of recursive flattening 【发布时间】:2017-01-10 06:29:00 【问题描述】:

美好的一天!

任务是获取数组的平面版本,其中可能包含一定数量的嵌套数组以及其他元素。对于输入 [1, [2], [3, [[4]]]] 输出 [1, 2, 3, 4] 预期。 FreeCodeCamp 剧透警告。 自然会想到递归解决方案,例如:

function steamrollArray(arr) 
  var result = [];
  for(var i = 0; i < arr.length; i++)
      //part of interest
      if (Array.isArray(arr[i]))
        var nestedElements = steamrollArray(arr[i]);
        for(var j = 0; j < nestedElements.length; j ++)
          result.push(nestedElements[j]);
        
      //</part of interest>.
       else 
        console.log("pushing: " + arr[i]);
        result.push(arr[i]);
      
  
  return result;

它确实做到了。样品运行的结果是:

pushing: 1
pushing: 2
pushing: 3
pushing: 4
[1, 2, 3, 4]

问题是:当我们使用 concat 添加 nestedElements (据说存储递归调用的返回结果)时,出了什么问题。如果我们要更改for 循环中的第一个if 块(标记为感兴趣的一部分),请使用下面的sn-p:

if (Array.isArray(arr[i]))
    var nestedElements = steamrollArray(arr[i]);
    result.concat(nestedElements);
 else 

我们将观察到以下结果:

pushing: 1
pushing: 2
pushing: 3
pushing: 4
[1]

我的理解是将每次递归调用的结果传递给concat 函数,该函数会将返回的数组添加到结果中,但由于某种原因并非如此。 有人问过这个任务的问题,比如this one,但是那些与扁平化算法部分有关的问题,这里不予质疑。 我仍然看不到答案究竟是什么导致了这种差异。这很可能是我在麻烦中或由于我有限的经验而忽略的事情。对不起,如果是这样的话。

【问题讨论】:

Array.concat 将创建一个新数组并将元素附加到其中,结果是一个全新的数组。 Array.concat 是不可变的,Array.push 是可变的。您可能需要再次将 concat 操作的结果存储到 nestedElements 中。 我想我的教训是仔细检查我使用的工具的规范,特别是当很明显确切的代码行导致意外行为时。感谢您的帮助! 【参考方案1】:

这是我的职责。

   function _recursive_array_flat( ...args )
   
       var _ret_array = [];
       for( _arg of args )
       
           if ( _arg instanceof Array )
           
               if ( _arg.length > 0 ) // work with consistent elements only
               _ret_array = _ret_array.concat( _recursive_array_flat( ..._arg ) );
           
           else _ret_array.push( _arg );
       

       return _ret_array;
    

    var _ret = _recursive_array_flat( [0], 1,2,3, [ 4,5,6, [ 7,8,9 ] ] );
    console.log( _ret );

【讨论】:

【参考方案2】:

我对接受的答案感到困惑,因为它只能连接两个数组。你想要的嵌套数组实际上是:

var flatArray = [].concat.apply([], yourNestedArray);

【讨论】:

【参考方案3】:

Array#concat 返回一个带有结果的新数组。

concat() 方法返回一个新数组,该数组由调用它的数组与作为参数提供的数组和/或值相连接。

所以你需要分配结果:

result = result.concat(nestedElements);
// ^^^^^^ assignment

【讨论】:

以上是关于用于递归展平结果的 JS 数组串联的主要内容,如果未能解决你的问题,请参考以下文章

Javascript递归数组展平

递归地展平数组(不循环)javascript

用于展平多维数组的函数[重复]

Javascript:使用递归将多维数组展平到位

使用递归(并且不使用循环)展平嵌套数组

在Ruby中递归地展平数组[重复]