了解递归遍历,并简化示例

时间:2018-12-15 21:21:07

标签: javascript

我试图理解递归横向。

我偶然发现了这个link,他们在上面写了一个这样的例子

let company = { // the same object, compressed for brevity
  sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 600 }],
  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)); // 6700

现在,我去模糊地阅读了关于reduceof的内容,我无法将其与本示例联系起来

as per this article

  

在此回调中,我们得到两个参数sum&elem。总和是   reduce函数的最后一个返回值。例如最初   当回调在第一个元素上运行时,总和将为0   它将elem加到和并返回该值。在第二   迭代总和值将是第一个elem + 0,在第三次迭代中   将会是0 +第一个elem +第二个elem。

现在,该示例是数组,而对象是对象,但是我仍然无法连接如何 current.salary等于薪水吗?

然后我真的无法理解这一行

for (let subdep of Object.values(department)) {
      sum += sumSalaries(subdep); // recursively call for subdepartments, sum the results
    }

就像我了解他正在递归地调用sumSalaries一样,但是..对我来说仍然没有意义吗?

有人可以请详细解释一下吗?

2 个答案:

答案 0 :(得分:1)

let subdep of Object.values(department)

department不是数组时,它将遍历值。当sumSalaries 首先使用company进行调用,因为company不是数组,所以我们按了下面这行代码。 company的值是sales数组和development对象-这些值都传递到sumSalaries中。

让我们看一下逻辑如何与纯数字值一起工作的简化示例:

const test = {
  sites: 3800,
  internals: 1300
}

let sum = 0;
for (let aggSalaries of Object.values(test)) {
  sum += aggSalaries;
}
console.log(sum)
  

5100

我建议可以将代码简化为:

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

function sumSalaries(department) {
  return Array.isArray(department)
    ? department.reduce((prev, {salary}) => prev + salary, 0)
    : Object.values(department).reduce((memo, value) => memo + sumSalaries(value), 0);
}

console.log(sumSalaries(company));

答案 1 :(得分:1)

让我们逐步完成代码:

1)函数

function sumSalaries(department) {

sumSalaries接受一个参数。最初,它将是一个对象company,但是在对象属性的连续迭代中,它将是一个数组或一个对象。

2)条件

  if (Array.isArray(department)) {

我们有一个需要满足的条件。如果参数是一个数组,请使用reduce对薪水值求和。最初company对象不满足此条件。

sales数组以及department对象中的两个数组都将满足此条件。

3)reduce

    return department.reduce((prev, current) => prev + current.salary, 0);

reduce接受一个初始值0,该初始值始终是每次迭代中回调函数中的第一个参数。在这种情况下,它被称为prev,但是对于“累加器”或acc,它可以很容易地称为sum。第二个参数current是数组中的当前元素。

重要说明:这些数组中的元素都是对象

因此,我们从prev中传递0到current中第一个数组对象开始,然后将在对象的salary属性中找到的值相加为零。此值在下一次迭代时作为prev参数传递。我们一直在增加该值,直到没有更多元素可以迭代为止,然后返回结果。

4)如果不符合条件

  } else {
    let sum = 0;

company对象和development对象都符合此条件。

5)迭代函数调用

    for (let subdep of Object.values(department)) {
      sum += sumSalaries(subdep);
    }
    return sum;
  }
}

在第一次迭代中,我们遍历了company。它的值是一个数组(sales)和另一个对象(development)。数组和对象被反馈到函数中。减少数组并将值添加到sum中,对象命中再次满足此条件,并且每个数组(sitesinternals)再次反馈到函数中,并且他们的结果会被减少并加到总和中。

就是这样!希望有帮助。