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

Posted

技术标签:

【中文标题】递归地展平数组(不循环)javascript【英文标题】:Flattening an array recursively (withoout looping) javascript 【发布时间】:2015-12-06 21:30:29 【问题描述】:

我正在练习递归,并试图在不循环的情况下展平数组(仅限递归)。作为第一步,我采用了迭代方法,它奏效了,但我坚持使用纯递归版本:

function flattenRecursive(arr) 
    if (arr.length === 1) 
        return arr;
    

    return Array.isArray(arr) ? arr = arr.concat(flattenRecursive(arr)) : flattenRecursive(arr.slice(1))


console.log(flattenRecursive([
    [2, 7],
    [8, 3],
    [1, 4], 7
])) //should return [2,7,8,3,1,4,7] but isn't - maximum call stack error


//working version (thanks @Dave!):

function flattenRecursive(arr) 
    if (arr.length === 1) 
        return arr;
    

    return arr[0].concat(Array.isArray(arr) ? flattenRecursive(arr.slice(1)) : arr);


console.log(flattenRecursive([
    [2, 7],
    [8, 3],
    [1, 4], 7
]))

//returns [ 2, 7, 8, 3, 1, 4, 7 ]

【问题讨论】:

提示:Array.isArray(arr) 永远为真 arr.concat(flattenRecursive(arr)) 导致无限递归。 @charlietfl - 第一次调用该函数时为真,然后使用相同的参数再次调用该函数 - arr - 因此将始终为真。它永远不会到达数组中的最后一项。 只是好奇为什么要递归执行此操作。如果您不想就地执行它,那么执行它是微不足道的。这是一个思考练习吗? @torazaburo 巩固我对递归的理解的练习(学术):) 你将如何做到这一点? 【参考方案1】:

这是一个稍微不那么冗长的工作版本。

//using reduce
function flattenRecursive(arr) 
  return arr.reduce(function(result, a)
    return result.concat(Array.isArray(a) ? flattenRecursive(a) : a);
  , []);


//without reduce
function flattenRecursive2(arr) 
  if (arr.length === 0)
    return arr;

  var head = arr.shift();
  if (Array.isArray(head))
    return flattenRecursive2(head).concat(flattenRecursive2(arr));
  else
    return [head].concat(flattenRecursive2(arr));


var testArray = [1,[2, 3],[[4, 5, [6, 7]], [8, 9]], 10];
console.log(flattenRecursive(testArray));
console.log(flattenRecursive2(testArray));
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

【讨论】:

嘿@dave 太棒了,但内部 reduce 使用 each,这本质上是一个 for 循环。根据您提供的解决方案,我正在乱搞,有时 sh$t 就可以了!将我上面的代码更新为有效的解决方案,感谢您的启发! @devdropper87 - 如果数组中的第一个元素不是数组,则递归函数将失败 - 例如console.log(flattenRecursive([7, [2, 7], [8, 3], [1, 4], 7 ])) 我很难过,如果它不是数组,我会尝试做一个 else ,但这不起作用。你有什么建议? @dave 有什么建议吗? @devdropper87 我添加了一个不使用.reduce()的替代方案@ @torazaburo 第二个示例现在已针对所有嵌套数组情况进行修复。【参考方案2】:

对不起,我没有评论的声誉。这是我的 2 美分。

1) 注意你的初始状态。在这里,如果您的输入是̀arr = [[1,2]],您的函数似乎返回[[1,2]],而您希望它返回[1,2]

2) 在递归的核心中,您必须确保使用smaller argument. Here, you should concat the first element of your array with the flattened rest of the array. The functionslice` 递归调用您的函数可能会很方便。

3) 也可以使用类reduce 函数。

【讨论】:

以上是关于递归地展平数组(不循环)javascript的主要内容,如果未能解决你的问题,请参考以下文章

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

递归展平列表[重复]

Javascript递归数组展平

如何在不循环的情况下展平一个简单的数组?

在 C# 中展平数组 [重复]

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