So I have an array of people, with their names and money.
const people = [ { name: 'Marcus Ericsson', money: 150, address: 'UK, Briston 5555' }, { name: 'Marcus Ericsson', money: 240, address: 'UK, Briston 5555' }, { name: 'Andre Balopos', money: 130, address: 'UK, Swansea 4321' }, { name: 'Lisa Stewart', money: 250, address: 'UK, Swansea 7654' }, { name: 'Andre Balopos', money: 90, address: 'UK, Swansea 4321' } ]
I want, using lodash and chaining, to return an object with the name and money of richest person even if that person has multiple objects in the array, summarizing the total amount of money. Return object should look something like this, without address.
{ name: Markus, money: 390 },
The steps in my mind
- Sum the money for all duplicate persons in the array into new array.
- Find the highest money value. max()?
- Return new object of richest person.
I’m new to lodash and functional programming. lodash documentation and chaining doesn’t make much sense to me at this stage, lots of terminology I don’t understand like iteratee, guarded, identity…etc
Which functions can I use to achieve this?
Advertisement
Answer
Using regular Lodash:
- Use
_.groupBy()
to collect values together based on name. This results in an object like:
{ "Marcus Ericsson": [ { name: "Marcus Ericsson", money: 150, address: "UK, Briston 5555" }, { name: "Marcus Ericsson", money: 240, address: "UK, Briston 5555" } ], "Andre Balopos": [ { name: "Andre Balopos", money: 130, address: "UK, Swansea 4321" }, { name: "Andre Balopos", money: 90, address: "UK, Swansea 4321" } ], "Lisa Stewart": [ { name: "Lisa Stewart", money: 250, address: "UK, Swansea 7654" } ] }
- Collapse the groups using
_.mapValues()
and_.sumBy
themoney
property. Result is:
{ "Marcus Ericsson": 390, "Andre Balopos": 220, "Lisa Stewart": 250 }
- Use
_.entries()
to get key-value pairs and_.map()
them into objects withname
andmoney
properties using_.zipObject()
(Credit to Ori Drori):
[ { name: "Marcus Ericsson", money: 390 }, { name: "Andre Balopos", money: 220 }, { name: "Lisa Stewart", money: 250 } ]
- Pick the object with highest money value with
_.maxBy
.
This can be achieved with implicit chaining:
const people = [ { name: 'Marcus Ericsson', money: 150, address: 'UK, Briston 5555' }, { name: 'Marcus Ericsson', money: 240, address: 'UK, Briston 5555' }, { name: 'Andre Balopos', money: 130, address: 'UK, Swansea 4321' }, { name: 'Lisa Stewart', money: 250, address: 'UK, Swansea 7654' }, { name: 'Andre Balopos', money: 90, address: 'UK, Swansea 4321' } ] const result = _(people) .groupBy("name") // 1. Group .mapValues(arr => _.sumBy(arr, "money")) // 2. Collapse the groups .entries() // 3. Get entries... .map(values => _.zipObject(["name", "money"], values) // 3. ...and convert ) .maxBy("money"); // 4. Get max console.log(result);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
The same can also be done using Lodash FP by composing functions into a chain of operations:
const { entries, flow, groupBy, map, mapValues, maxBy, sumBy, zipObject } = _; const people = [ { name: 'Marcus Ericsson', money: 150, address: 'UK, Briston 5555' }, { name: 'Marcus Ericsson', money: 240, address: 'UK, Briston 5555' }, { name: 'Andre Balopos', money: 130, address: 'UK, Swansea 4321' }, { name: 'Lisa Stewart', money: 250, address: 'UK, Swansea 7654' }, { name: 'Andre Balopos', money: 90, address: 'UK, Swansea 4321' } ]; const pipeline = flow( groupBy("name"), mapValues(sumBy("money")), entries, map(zipObject(["name", "money"])), maxBy("money") ); const result = pipeline(people); console.log(result);
<script src="https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)"></script>