问题
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
回答1:
/* 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) */ }
But there is something odd about that code. First, it uses reduce
to total the values in one case and sum = 0 ... for (...) { sum += ... } ... return sum
for the other; that feels odd. Second, it uses a substantially different variable name for the internal variable you're going to supply as a parameter to the recursive call. But the data structure does not suggest that; the company is structured the same as any department or sub-department. This distinction between "department"
and "subdep"
makes it more difficult to get a feeling for the recursive nature of the problem. Usually, when I need two different names for the data structure, I try to make the names seem aligned. I might, for instance, use the abbreviation dept
instead of subdep
.
So, I would write this differently. Here's a different version, using a helper function which sums an array of numbers. While it looks quite different, the underlying logic is entirely the same:
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))
回答2:
It is because the line sum += sumSalaries(subdep)
creates a bunch of function calls and each of them are independent.
Let's break the loop into single function calls
for (let subdep of Object.values(department)) {
sum += sumSalaries(subdep); // recursively call for subdepartments, sum the results
}
is merely
sum += sumSalaries(department.sales);
sum += sumSalaries(department.development);
Each of the function call above will execute on its own and return the value. So, when the first call returns something, it just finishes its own function, not the root function.
来源:https://stackoverflow.com/questions/60587625/recursion-example-of-application-of-the-recursion