Reputation: 11850
I was trying to understand Recursive Transversal.
I stumbled upon this link where they wrote something like this for an example
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
Now, I went and read about reduce
and of
vaguely and I am unable to connect it with this example
Like as per this article
Inside this callback we get two arguments sum & elem. The sum is the last returned value of the reduce function. For example initially the sum value will be 0 then when the callback runs on the first element it will add the elem to the sum and return that value. On second iteration the sum value will be first elem + 0, on third iteration it will be 0 + first elem + second elem.
Now, that example was with array and this is with object but still I am unable to connect how can current.salary
be equal to the salary?
Then I am literally unable to comprehend this line
for (let subdep of Object.values(department)) {
sum += sumSalaries(subdep); // recursively call for subdepartments, sum the results
}
Like I understand he is calling sumSalaries recursively but.. Still make no sense to me?
Can someone please-please explain this in stretch?
Upvotes: 0
Views: 98
Reputation: 63525
Let's step through the code:
function sumSalaries(department) {
sumSalaries
accepts one argument. Initially this will be an object company
, but over successive iterations of the object properties this will be either an array or an object.
if (Array.isArray(department)) {
We have a condition to be satisfied. If the argument is an array, sum the salary values using reduce
. Initially the company
object doesn't meet this condition.
The sales
array, and both arrays from the department
object will meet this condition.
reduce
return department.reduce((prev, current) => prev + current.salary, 0);
reduce
accepts an initial value 0 that will always be the first argument in the callback function on each iteration. In this instance it's called prev
, but could easily be called acc
for "accumulator", or sum
, for example. The second argument current
is the current element in the array.
Important note: the elements in these arrays are all objects.
So we start with 0 passed in prev
and the first array object in current
and we add the value found in that object's salary property to zero. This value is passed in as the prev
argument on the next iteration. We keep adding to this value until there are no more elements to iterate over, and then the result is returned.
} else {
let sum = 0;
Both the company
object, and the development
object match this condition.
for (let subdep of Object.values(department)) {
sum += sumSalaries(subdep);
}
return sum;
}
}
On the first iteration we're looping over company
. Its values are one array (sales
) and another object (development
). The array and object get fed back into the function. The array gets reduced and the value added to sum
, and the object hits satisfies this condition again and each array (sites
, internals
) is fed back into the function again and their results are reduced and added to the sum.
And that's it! Hope that helps.
Upvotes: 1
Reputation: 14927
let subdep of Object.values(department)
This iterates over the values when department
is not an array. When sumSalaries
is first called with company
, we hit this line of code because company
is not an array. The values of company
are the sales
array and the development
object - these values are both passed into sumSalaries
.
Let's look at a simplified example of how the logic would work with pure number values:
const test = {
sites: 3800,
internals: 1300
}
let sum = 0;
for (let aggSalaries of Object.values(test)) {
sum += aggSalaries;
}
console.log(sum)
5100
I would suggest the code can be simplified to:
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));
Upvotes: 1