首页 > 解决方案 > 递归操作然后跳出循环

问题描述

我有一个存储部门层次结构的对象。每个部门也可能有子部门。我正在尝试循环检查所有部门以及子(子)部门属性Open

但是,每当我进行递归调用时,它只会迭代一次并直接跳转到return true,即使仍有一些项目尚未在循环中检查。

validateDepartment(departmentHierarchy: any) {
      for (let dept of departmentHierarchy.children) {
          if (dept!= undefined && dept!= null) {
            if (dept.instance.status == "Open")
            {
              continue
            }
            else
            {
                if (dept.children != undefined && dept.children != null) {
                    this.validateDepartment(dept);
                }
                else {
                    return false
                }
            }
          }
      }
      return true
  }

标签: javascriptangularjsangulartypescript

解决方案


不是任何答案的一部分,但它有助于只编写“做”事情的代码,而不是有很多代码来做“代码已经做的事情”,例如continue在迭代代码是单个 if 时调用/别的。我们可以将您的代码重写为此,并有一些更容易使用的东西:

validateDepartment(tree: any) {
  // step 1: do any validation of the top node
  if (!validateTopNodeOnly(tree)) {
    // this is a stop condition.
    return false;
  }

  if (!tree.children) {
    // this is also a stop condition, but for a different reason.
    // a department without children should not _necessarily_ be invalid.
    return true? return false? probably return true since the node itself is fine.
  }

  if (tree.instance && tree.instance.status !== "open") {
    // and this is a third  condition, but for yet another reason.
    // I'm guessing this is also not "invalid", just means we shouldn't recurse.
    return true? return false? probably return true as well.
  }

  // Then, get all (non-falsey) children,
  let children = tree.children.filter(e => e);

  // and iterate over them:
  for (let e of children) {
    let result = this.validateDepartment(e);

    // cut your run short if validation fails
    if (result === false) {
      return false;
    }
  }

  // and this is the expected stop condition for a normal run.
  return true;
}

但是使用真/假是非常幼稚的,并且不会告诉您验证失败的任何地方,因此您需要处理“失败的原因”,通常是通过返回对实际“正在验证的事物”的引用,这样如果你的函数返回true,一切都很好,它返回一些东西!== true然后你就知道它失败了,它返回的东西是出现问题的部门。

另请注意,通过使用验证失败的早期返回,您会丢失信息:相反,最好使用.map()和构建所有通过/失败验证的部门的运行计数,以便您返回一个数组,其中要么result.every(e => (e===true))是true 或 false,在这种情况下result.filter(e => (e!==true))为您提供每个失败部门的集合。


推荐阅读