The goal in this example is to count the number of books each author has written, from a list of book objects.
Example input:
const books = [
{ author: "Jane", name: "Foo: a bar" },
{ author: "John", name: "Tale of Zim" },
{ author: "Jan", name: "Legend of Gir" },
{ author: "Jane", name: "Zig 2: the sequel" },
];
Expected output:
const authorCounts = {
"Jane": 2,
"John": 1,
"Jan": 1,
};
Starting with a non-functional solution:
function countAuthors(books) {
const authorCounts = {};
for (const book of books) {
if (!authorCounts[book.author]) {
authorCounts[book.author] = 0;
}
authorCounts[book.author]++;
}
return authorCounts;
}
This uses a loop to build up a new object, pretty standard, but this is pretty much a unit, we couldn't easily decompose this.
For a functional example, I'm using lodash because javascript doesn't have a great amount of functional utilities:
import { mapValues, groupBy } from 'lodash';
function countAuthors(books) {
return mapValues(groupBy(books, 'author'), (books) => books.length);
}
Here we just do 2 transformations, first grouping the list of books into a dictionary keyed by author name, and then taking the length of the inner array of books.
This is now a simple pipeline, and much shorter than the original.