I would tackle this without using D3 at all, with JSās reduce function.
[Not having much experience with functional programming, I remember being quite confused by the syntax at first, but I think the examples on that doc page are really helpful.] Hereās a quick intro:
Typically whenever I have an array and I want to get a single value out of it in some way, I think about using reduce
if I can. The way it works is as follows: you want to write a function which takes two inputs, the āaccumulatorā and the ācurrent valueā and which returns a new value of the accumulator. This function is called on each element of the array starting with 0 and ending with the last element (if you want to go backwards, you can use reduceRight
).
For instance, to sum a numerical array, we would write a function:
function sum(acc, val) {
return acc + val;
}
and use this in reduce
as follows (the 0
is the initial value of the accumulator variable):
[0,1,4,2,4,5].reduce(sum, 0)
We can also use āarrow notationā to avoid having to write a separate function:
[0,1,4,2,4,5].reduce((a,b) => a+b, 0)
For your problem, where you want to sum the quantities of the objects, Iād write something like this for totalFruit
and totalVeg
:
function sumQuantities(acc, val) {
// we only care about the quantity field of the object
return acc+val.quantity;
}
totalFruit = fruits.reduce(sumQuantities, 0);
totalVeg = veg.reduce(sumQuantities, 0);
To get totalBasket, you can merge the arrays before applying reduce
; remember that the .concat
method concatenates arrays:
basket = fruits.concat(veg);
totalBasket = basket.reduce(sumQuantities, 0);
If you have more stuff to sum in the basket, note that you can do this (assuming the data format is the same):
basket = fruits.concat(veg, meat, fish, bread);
totalBasket = basket.reduce(sumQuantities, 0);
And yeah, Iāve also always thought that the d
convention stood for data
.
EDIT: The following alternate approach which avoids the cost of concatenation might also be enlightening:
basketArr = [fruits, veg, meat, fish, bread];
totalBasket = basketArr.reduce(
(acc, arr) => arr.reduce(sumQuantities, acc),
0);
The inner reduce
does the same thing as the ones above, except that the initial value is set to acc
instead of zero. The outer reduce
makes it so that acc
contains a running total of the sums of arrays that have already been looked at.