Who can kindly explain the accumulator acc construction below in plain English?
return arr1.reduce(function(acc, curr){
var last = acc[acc.length-1];
if(acc.length > 0 && curr[1]===last[1]) {
last[0] += curr[0];
} else acc.push(curr);
return acc;
}, []);
}
This reduce
method can be used to solve the FreeCodeCamp "Inventory Update" assignment, as part of their advanced algorithm scripting lessons.
One is required to update existing items in an inventory array (arr1) with new items in a "new delivery" array.
Two test arrays, a present inventory curInv and a new delivery newInv respectively, could be as follows:
var curInv = [
[21, "Bowling Ball"],
[2, "Dirty Sock"],
[1, "Hair Pin"],
[5, "Microphone"]
];
var newInv = [
[2, "Hair Pin"],
[3, "Half-Eaten Apple"],
[67, "Bowling Ball"],
[7, "Toothpaste"]
];
After finding several excellent articles on Javascript reduce method (such this post and a great video course on egghead.io), and somehow sensing the power it is harnassing, I would read the method as follows:
Reduce the inventory array, by creating an empty array [ ] first (the initial value), then applying the following callback function:
If the inventory array is currently not empty (has a length greater than zero), and the name of currently handled item (index 0 of curr could read "Bowling Ball" for example) is identical to the last item of the inventory array being updated, then update the amount of this item in the inventory array.
The last item is defined right above the if statement, as follows: take the present length of the accumulated array upto now, subtract 1, and use this value to index the accumulated array. The element at that index is then assigned to the variable 'last'.
On the other hand, if the inventory is empty, add the new item entirely, - that is: item name and amount. Now return the newly accumulated array."*
How is using the
length - 1
of the accumulator useful to make acc actually accumulate? (pardon the alliteration)
I think I understand most of how this reduce method is built, but please correct me wherever I'm misreading), except this particular
use of acc.length-1
.
Cheers, k.
The actual solution involves concatenating and sorting both arrays and only then reducing them. In this case whenever we evaluate a new item, if its name is not equal to the last accumulator item, it means it's a new item.
Using your example, the list we are reducing is:
[
[ 21, 'Bowling Ball' ],
[ 67, 'Bowling Ball' ],
[ 2, 'Dirty Sock' ],
[ 1, 'Hair Pin' ],
[ 2, 'Hair Pin' ],
[ 3, 'Half-Eaten Apple' ],
[ 5, 'Microphone' ],
[ 7, 'Toothpaste' ]
]
so when we encounter the second item, the last value in the accumulator is [21, 'Boweling Ball']
and when we compare the strings we go into the first condition.