javascript - 递归,递归应用示例

标签 javascript recursion

let company = { 
  sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 1600 }],
  development: {
    sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],
    internals: [{name: 'Jack', salary: 1300}]
  }
};

// The function to do the job
function sumSalaries(department) {
  if (Array.isArray(department)) { // case (1)
    return department.reduce((prev, current) => prev + current.salary, 0); // sum the array
  } else { // case (2)
    let sum = 0;
    for (let subdep of Object.values(department)) {
      sum += sumSalaries(subdep); // recursively call for subdepartments, sum the results
    }
    return sum;
  }
}

alert(sumSalaries(company)); // 7700
这段代码是关于使用递归计算公司各部门的工资总额。 请向我解释一下这一点。在教程的例子中,递归遍历,运行第一个案例(我们计算销售部门的工资)函数后返回这个工资。那么,如果我们在第一次计算中有 return 语句,为什么还要继续计算另一个案例(开发部门)呢?不应该破坏流量吗?以及它如何将情况 1 与情况 2 的总和相加?

最佳答案

/*  1 */ function sumSalaries(department) {
/*  2 */ if (Array.isArray(department)) { // case (1)
/*  3 */     return department.reduce((prev, current) => prev + current.salary, 0); // sum the array
/*  4 */   } else { // case (2)
/*  5 */     let sum = 0;
/*  6 */     for (let subdep of Object.values(department)) {
/*  7 */       sum += sumSalaries(subdep); // recursively call for subdepartments, sum the results
/*  8 */     }
/*  9 */     return sum;
/* 10 */   }
/* 11 */ }
/*  (1) */ sumSalaries (company) {
/*  (2) */   Array .isArray (company) //=> false, so hit branch 2
/*  (5) */     sum = 0
/*  (6) */     Object .values (company) //=> [<sales>, <development>]
/*  (6) */     [<sales>, <development>] .for Each ... 
/*  (7) */       sumSalaries (<sales>) {
/*  (2) */         Array .isArray (<sales>) //=> true, so hit branch 1           //       John   Alice
/*  (3) */           <sales>.reduce((prev, current) => prev + current.salary, 0) //=> 0 + 1000 + 1600 = 2600
/*  (3) */           return 2600
/* (10) */       }
/*  (7) */       sum = 0 + 2600 = 2600
/*  (7) */       sumSalaries (<development>) {
/*  (2) */         Array.isArray (<development) //=> false, so hit branch 2
/*  (5) */           sum = 0  // (different instance of `sum` from above)
/*  (6) */           Object.values (<development>) //=> [<sites>, <internal>]
/*  (6) */           [<sites>, <internal>] .for Each ...  
/*  (7) */             sumSalaries (<sites>) {
/*  (2) */               Array.isArray (<sites>) //=> true, so hit branch 1            //       Peter  Alex
/*  (3) */                 <sites>.reduce((prev, current) => prev + current.salary, 0) //=> 0 + 2000 + 1800 = 3800
/*  (3) */                 return 3800
/* (10) */             }
/*  (7) */             sum = 0 + 3800
/*  (7) */             sumSalaries (<internals>) {
/*  (2) */               Array.isArray (<internals>) //=> true, so hit branch 1               Jack
/*  (3) */                 <internals>.reduce((prev, current) => prev + current.salary, 0) //=> 0 + 1300 = 1300
/* (10) */                 return 1300
/* (10) */             }
/*  (7) */             sum = 3800 + 1300 = 5100
/*  (9) */           return 5100
/* (10) */       }
/*  (7) */       sum = 2600 + 5100 = 7700  // (back to the original `sum`)
/*  (9) */       return 7700
/* (11) */ }
<小时/>

但是该代码有一些奇怪的地方。首先,它使用 reduce 对一种情况下的值求和,并使用 sum = 0 ... for (...) { sum += ... } ... return sum 为其他;这感觉很奇怪。其次,它对要作为参数提供给递归调用的内部变量使用完全不同的变量名称。但数据结构并没有表明这一点;公司的结构与任何部门或子部门相同。 “department”“subdep” 之间的区别使得更难了解问题的递归本质。通常,当我需要数据结构的两个不同名称时,我会尝试使这些名称看起来对齐。例如,我可能会使用缩写 dept 而不是 subdep

所以,我会以不同的方式写这个。这是一个不同的版本,使用辅助函数对数字数组求和。虽然看起来很不同,但底层逻辑完全相同:

const sum = (ns) => ns .reduce ((t, n) => t + n, 0)

const sumSalaries = (department) =>
  Array .isArray (department) 
    ? sum (department .map (empl => empl .salary))
    : sum (Object .values (department) .map (sumSalaries))

const company = {sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 1600 }], development: {sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }], internals: [{name: 'Jack', salary: 1300}]}}

console .log (sumSalaries (company))

关于javascript - 递归,递归应用示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60587625/

相关文章:

delphi - 递归文件搜索线程

java - 有没有更好的方法来使用等待/通知与 AtomicInteger 连接

javascript - 下载脚本生成的html

Javascript 拖动事件不起作用

javascript - 在 React 中将空值设置为数字文本框

javascript - 如何为多选中的选项设置默认值?

javascript - 使用 Google Sheets 将 HTML 编码为 HTML 特殊字符

regex - 捕获量词和量词算术

c++ - 将递归置换生成器转换为迭代

f# - 我的 rec 函数是尾递归的吗?