【问题标题】:Flatten a arrays inside array using recursion使用递归展平数组内的数组
【发布时间】:2019-06-30 01:27:00
【问题描述】:

您能告诉我为什么这段代码不能正常工作吗?

flatten 函数假设从输入数组中的任何数组中删除值并将这些值作为数组返回。

function flatten(arr) {
  //create a new array
  let newArr = [];

  //create a helperFunction
  function helperFunction(helperArr) {
    //if its an empty array
    if (helperArr.length === 0) {
      return;
    }

    //get the first value from the array and remove the value
    let firstArrVal = helperArr.shift();
    let isAnArray = Array.isArray(firstArrVal);

    //if value is an array 
    if (isAnArray) {
      //call recursive function on value
      return helperFunction(firstArrVal);
    }
    //if value isnt an array
    else {
      //add value to new array
      newArr.push(firstArrVal);
      //call recursive function on the array
      return helperFunction(helperArr);
    }
  }

  //call helperFunction
  helperFunction(arr);

  //return new array
  return newArr;
}

console.log(flatten([1, [2, [3, 4],
  [
    [5]
  ]
]]));

// Correct output - [1, 2, 3, 4, 5] - Mine - [1, 2, 3, 4]

对于输入[1, [2, [3, 4], [[5]]]],正确的输出是[1, 2, 3, 4, 5](我的 - [1, 2, 3, 4]

【问题讨论】:

    标签: javascript arrays recursion


    【解决方案1】:

    您需要遍历子数组的所有元素,然后对它们进行push 或对它们调用helperFunction。你现在的

        let firstArrVal = helperArr.shift();
        let isAnArray = Array.isArray(firstArrVal);
    

    只会合并第一个嵌套值,但不会合并第 0 个之后的任何嵌套索引。对数组中的每个值使用 for 循环:

    function flatten(arr) {
      //create a new array
      let newArr = [];
    
      //create a helperFunction
      function helperFunction(helperArr) {
        //if its an empty array
        if (helperArr.length === 0) {
          return;
        }
        for (let i = 0; i < helperArr.length; i++) {
          const val = helperArr[i];
          let isAnArray = Array.isArray(val);
    
          //if value is an array 
          if (isAnArray) {
            //call recursive function on value
            helperFunction(val);
          }
          //if value isnt an array
          else {
            //add value to new array
            newArr.push(val);
          }
        }
      }
    
      //call helperFunction
      helperFunction(arr);
    
      //return new array
      return newArr;
    }
    
    console.log(flatten([1, [2, [3, 4],
      [
        [5]
      ]
    ]]));

    或者,为了更简洁,使用flat(为不兼容的浏览器添加polyfill):

    const flatten = arr => arr.flat(Infinity);
    
    console.log(flatten([1, [2, [3, 4],[[5]]]]));

    【讨论】:

    • 感谢您的快速回复@CertainPerformance。我试图在不使用任何循环的情况下做到这一点。我认为这可以在没有任何循环的情况下完成。我想通过递归我们只能线性旅行。再次感谢。
    • 除非每个嵌套数组都只包含一个元素,否则您必须使用某种循环来遍历每个元素并检查它是数组还是普通值。
    • 当某个答案对您有帮助时,您可以考虑将其标记为已接受,表示您的问题已解决:)
    【解决方案2】:

    您的代码的问题是您没有迭代(子)数组元素 - 作为替代,您可以在以下 recursive 函数中使用 flatMap(和 fat arrow

    let arr=[1, [2, [3, 4], [[5]]]];
    let flatten = a => a.flatMap(x=> Array.isArray(x) ? flatten(x) : x);
    
    console.log(flatten(arr));

    【讨论】:

    • 感谢您指出我的错误。我现在意识到不可能使用递归遍历多维对象。感谢您的帮助。
    • @DilanWaduge 我不明白你所说的“多维对象”是什么意思 - 但是上面的 flatten 函数是递归的(它在它的主体内部调用自身)并且它通过多维数组(所以在数组的情况下是可能的)
    • 我指的是对象中的对象。就像你说的 flatMap 只能在 JavaScript 数组上使用。感谢您指出 flatMap。这是一种有用的了解方法。
    • @DilanWaduge 我认为嵌套对象中的递归旅行是可能的 - 看here
    • 感谢您的链接。 for in 循环似乎可以解决问题。感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2015-08-15
    • 2015-12-06
    • 2020-10-30
    • 1970-01-01
    相关资源
    最近更新 更多