Skip to content
Advertisement

lodash new object from array of objects with properties

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

  1. Sum the money for all duplicate persons in the array into new array.
  2. Find the highest money value. max()?
  3. 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:

  1. 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" }
  ]
}
  1. Collapse the groups using _.mapValues() and _.sumBy the money property. Result is:
{
  "Marcus Ericsson": 390,
  "Andre Balopos": 220,
  "Lisa Stewart": 250
}
  1. Use _.entries() to get key-value pairs and _.map() them into objects with name and money properties using _.zipObject() (Credit to Ori Drori):
[
  { name: "Marcus Ericsson", money: 390 },
  { name: "Andre Balopos", money: 220 },
  { name: "Lisa Stewart", money: 250 }
]
  1. 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>
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement