【问题标题】:Recursive function returns undefined regardless of enough return statements无论是否有足够的返回语句,递归函数都返回未定义
【发布时间】:2020-03-24 11:41:47
【问题描述】:

我已经阅读了一些关于它的问题和答案。看起来我的递归函数有足够的“返回”语句,所以......我不知道它为什么返回未定义......我添加了额外的日志语句以显示函数本身找到了元素,但没有返回它...

let animals = [
  {
    name: "dogs",
    id: 1,
    children: [
      {
        name: "lessie",
        id: 2
      },
      {
        name: "bark-a-lot",
        id: 3
      }
    ]
  },
  {
    name: "cats",
    id: 4,
    children: [
      {
        name: "meows-a-lot",
        id: 5,
        children: [
          {
            name: "meows-a-lot-in-the-morning",
            id: 6
          }
        ]
      },
      {
        name: "whisk-ass",
        id: 7
      }
    ]
  }
];

function recurseFind(node, id) {
  if (Array.isArray(node)) {
    return node.forEach(el => {
      return recurseFind(el, id);
    });
  } else {
    if (node.id === id) {
      console.log("node matched", node.id, id, node);
      return node;
    } else if (node.children) {
      return node.children.forEach(child => {
        return recurseFind(child, id);
      });
    } else {
      return "not found";
    }
  }
}

const found = recurseFind(animals, 6);
console.log("found", found, "wtf");

【问题讨论】:

  • return node.forEach() - 你的问题,forEach 总是返回undefined。您可能打算使用.map.find(用于多个结果或一个)

标签: javascript recursion


【解决方案1】:

forEach 返回undefined,所以

return node.forEach(el => {
  return recurseFind(el, id);
});

将始终返回undefined,无论递归调用找到什么。

我会改用for 循环,如果找到匹配项,则返回:

let animals = [
  {
    name: "dogs",
    id: 1,
    children: [
      {
        name: "lessie",
        id: 2
      },
      {
        name: "bark-a-lot",
        id: 3
      }
    ]
  },
  {
    name: "cats",
    id: 4,
    children: [
      {
        name: "meows-a-lot",
        id: 5,
        children: [
          {
            name: "meows-a-lot-in-the-morning",
            id: 6
          }
        ]
      },
      {
        name: "whisk-ass",
        id: 7
      }
    ]
  }
];

function recurseFind(node, id) {
  if (Array.isArray(node)) {
    for (const el of node) {
      const result = recurseFind(el, id);
      if (result) return result;
    }
  } else {
    if (node.id === id) {
      return node;
    } else if (node.children) {
      for (const child of node.children) {
        const result = recurseFind(child, id);
        if (result) return result;
      }
    }
  }
}

const found = recurseFind(animals, 6) || 'not found';
console.log("found", found);

【讨论】:

    【解决方案2】:

    VLAZ 和CertainPerformance 已经指出了您的功能无法正常工作的原因。

    这是一种对我来说似乎更简单的替代技术:

    const recursiveFind = (pred) => (xs) => xs .reduce (
      (r, x) => r != null ? r : pred (x) ? x : recursiveFind (pred) (x.children || []) || null,
      null
    )
    
    const findById = (id) => recursiveFind(x => x.id == id)
    
    const animals = [{name: "dogs", id: 1, children: [{name: "lessie", id: 2}, {name: "bark-a-lot", id: 3}]}, {name: "cats", id: 4, children: [{name: "meows-a-lot", id: 5, children: [{ name: "meows-a-lot-in-the-morning", id: 6}]}, {name: "whisk-ass", id: 7}]}];
    
    console .log (findById (3) (animals))
    console .log (findById (4) (animals))

    我们从一个通用函数开始,它通过是否匹配提供的谓词函数来搜索以这种方式嵌套的对象。然后我们将谓词 x => x.id == id 传递给它,以创建一个函数,该函数接受一个 id 和一个值列表,并在列表中找到第一个具有匹配 id 的值,如果没有找到则 null

    如果你对这个 recursiveFind 函数完全没有用处,你可以像这样将它内联到 findById 中:

    const findById = (id, xs) => xs .reduce (
      (r, x) => r != null ? r : x.id == id ? x : findById (id, x.children || []) || null,
      null
    )
    
    findById (3, animals)
    

    但我实际上更愿意朝另一个方向发展,并使其更加通用,使用类似这样的东西:

    const recursiveFind = (pred, descend) => (xs) => xs .reduce (
      (r, x) => r != null ? r :  pred (x) ? x : recursiveFind (pred, descend) (descend (x) || []) || null,
      null
    )
    
    const findById = (id) => recursiveFind (x => x.id == id, x => x.children)
    
    findById (3) (animals)
    

    这个版本还参数化了我们如何下降到节点的子节点。在这种情况下,我们只是使用x => x.children,但很容易想象使用其他属性或更复杂的方法。

    在所有这些中,请注意该函数会处理嵌套数组结构的所有节点,即使我们已经找到了匹配项。如果我们有,第一次检查 (r != null) 会快速跳过,但如果性能很关键,您可能更喜欢具有显式短路循环的解决方案,例如来自“CertainPerformance”的解决方案。

    【讨论】:

      猜你喜欢
      • 2012-09-26
      • 1970-01-01
      相关资源
      最近更新 更多