javascript 为什么我的递归函数不返回数组中的最后一个元素?

izkcnapc  于 2023-01-16  发布在  Java
关注(0)|答案(3)|浏览(167)

所以我在学习FreeCodecamp的过程中,偶然发现了这个任务,我用一个for循环解决了这个任务。但是为了测试我对递归函数的知识,我想试一下。但是由于某种原因,最后的数组只包含了第三和第二个元素。
代码:
任务来源:
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/es6/create-strings-using-template-literals

const result = {
    success: ["max-length", "no-amd", "prefer-arrow-functions"],
    failure: ["no-var", "var-on-top", "linebreak"],
    skipped: ["no-extra-semi", "no-dup-keys"]
  };

  const failureItems = [];

  function makeList(arr) {
    // Only change code below this line
  
    // for (let i = 0; i < arr.length; i++)
    // {
    //   failureItems.push(`<li class="text-warning">${arr[i]}</li>`);
    // }  
    
    if(arr.length === 1){
      return arr[0];
    } else {
      failureItems.push(`<li class="text-warning">${arr.pop()}</li>`);
      if(arr.length >= 1){
        makeList(arr);}
    }
    console.log("Log before return:" + failureItems[0]);  
    // Only change code above this line
    return failureItems;
  }
  const failuresList = makeList(result.failure);
  console.log(`Failure list is ${failuresList}`);

我添加了consoleiderlog,我认为问题发生在哪里,但我就是找不到给我带来麻烦的行。

vh0rcniy

vh0rcniy1#

你永远不能按第一元素。
尽管递归可能不是你所用的最佳解决方案..但是你可以递归到数组为空为止

if(arr.length === 0){
      return;
    } else {
      failureItems.push(`<li class="text-warning">${arr.pop()}</li>`);
      if(arr.length >= 1){
        makeList(arr);}
    }
pvabu6sv

pvabu6sv2#

您的代码基本上是正确的,它没有给予每个输出的唯一原因是基本条件,即递归应该在哪里结束。
这里唯一适合推送元素的基本条件是直到数组为空,这允许您实际上也推送第一个元素。
修订后的守则如下:

const result = {
    success: ["max-length", "no-amd", "prefer-arrow-functions"],
    failure: ["no-var", "var-on-top", "linebreak"],
    skipped: ["no-extra-semi", "no-dup-keys"]
  };

  const failureItems = [];

  function makeList(arr) {
    
    // your base condition

    if(arr.length === 0){
      return;
    } else {
      failureItems.push(`<li class="text-warning">${arr.pop()}</li>`);
    }
    if(arr.length >= 1){
        makeList(arr);}
    console.log("Log before return:" + failureItems[0]);  
    
    // Only change code above this line
    return failureItems;
  }
  const failuresList = makeList(result.failure);
  console.log(`Failure list is ${failuresList}`);

递归函数被一个接一个地调用,用于数组中的每个元素,并且它被推入列表中,直到数组变为空,即
配置长度=== 0
如果有帮助的话,请投赞成票!

sr4lhrrt

sr4lhrrt3#

你的代码,即使被其他答案纠正过,也有两个真实的的问题。
首先,你在执行过程中反转数组,这是重复调用pop的结果,从右到左移动输入数组,然后用push将结果放在输出数组的末尾,现在从左到右移动。
第二,更糟糕的是,你正在以一种不可恢复的方式改变输入。通过调用pop,你正在破坏你的result对象。如果你在完成后记录它,你会看到result.failure现在是一个空数组。唉!
解决这些问题的一个简单方法是使用Array.prototype.map,通过对每个值应用相同的函数,将一个值数组转换为另一个值数组:

const makeList = (arr) => 
  arr .map (reason => `<li class="text-warning">${reason}</li>`)

const result = {
  success: ["max-length", "no-amd", "prefer-arrow-functions"],
  failure: ["no-var", "var-on-top", "linebreak"],
  skipped: ["no-extra-semi", "no-dup-keys"]
}

const failuresList = makeList (result .failure)
console .log (`Failure list is ${failuresList}`)

如果您真的想递归地执行此操作,可以尝试类似于

const makeList = (reasons) =>
  reasons .length == 0 
    ? []
    : [`<li class="text-warning">${reasons [0]}</li>`, ...makeList (reasons .slice (1))]

或者我更喜欢更简洁的说法:

const makeList = ([reason, ...reasons]) => 
  reason == undefined 
    ? [] 
    : [`<li class="text-warning">${reason}</li>`, ...makeList (reasons)]

相关问题