来自具有属性的对象数组的 lodash 新对象

lodash new object from array of objects with properties

所以我有很多人,有他们的名字和钱。

 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'
    }
]

我想使用 lodash 和链接 return 一个对象,其中包含最富有的人的姓名和金钱,即使该人在数组中有多个对象,也可以汇总金钱总额。 Return 对象应该看起来像这样,没有地址。

{
  name: Markus, 
  money: 390
},

我心中的脚步

  1. 将数组中所有重复的人的钱加到新数组中。
  2. 找出最高货币价值。最大()?
  3. Return首富新对象

我是 lodash 和函数式编程的新手。 lodash 文档和链接在这个阶段对我来说没有多大意义,很多术语我不理解,比如 iteratee、guarded、identity...等

我可以使用哪些函数来实现这一点?

对我来说,一个简单的 reduce 就可以完成工作:

let richest = 0;
let richestName;

const peopleMoneyMap = people.reduce((map, current) => {
  const { name, money } = current;
  map[name] = (map[name] || 0) + money;
  
  if (map[name] > richest) {
    richest = map[name];
    richestName = name;
  }
  
  return map;
}, {})

const result = {
  name: richestName,
  money: richest,
}

如果您登录 peopleMoneyMap,您将获得:

{
  "Andre Balopos": 220,
  "Lisa Stewart": 250,
  "Marcus Ericsson": 390,
}

按钱分组,映射组,并用 name 和每个组的 money 的总和创建一个对象,并使用 _.maxBy() 找到对象最大值 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"}]

const result = _(people)
  .groupBy('name')
  .map((group, name) => ({
    name,
    money: _.sumBy(group, 'money')
  }))
  .maxBy('money')

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous"></script>

使用常规 Lodash:

  1. 使用_.groupBy()根据名称收集值。这会产生一个像这样的对象:
{
  "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. 使用 _.mapValues() and _.sumBymoney 属性 折叠组。结果是:
{
  "Marcus Ericsson": 390,
  "Andre Balopos": 220,
  "Lisa Stewart": 250
}
  1. 使用_.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. _.maxBy选择货币价值最高的对象。

这可以通过 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>

也可以使用 Lodash FP 通过将函数组合成一系列操作来完成相同的操作:

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>