【问题标题】:merge partially duplicated arrays in javascript (lodash)在 javascript (lodash) 中合并部分重复的数组
【发布时间】:2019-05-01 06:35:11
【问题描述】:

我有很多人在不同年份买了一辆车。 简化后的数组是这样的:

const owners = [{
  name: "john",
  hasCar: true,
  yearBought: 2002
}, {
  name: "john",
  hasCar: true,
  yearBought: 2005
}, {
  name: "mary",
  hasCar: true,
  yearBought: 2015
}, {
  name: "john",
  hasCar: true,
  yearBought: 2018
}]

如果一个人拥有不止一辆汽车(如本例中的约翰),那么对于他购买汽车的不同年份会有不同的对象。我想合并属于每个人的对象,最终结果应该是这样的:

const owners = [{
  name: "john",
  hasCar: true,
  yearBought: [2002, 2005, 2018]
}, {
  name: "mary",
  hasCar: true,
  yearBought: 2018
}]

【问题讨论】:

  • 我认为您不需要 Lodash。只需检查具有给定名称的元素是否存在,如果存在,将年份推送到yearsBought,如果不存在,只需将新元素推送到列表中

标签: javascript arrays lodash


【解决方案1】:

您可以使用reduce 数组并首先根据name 对它们进行分组。累加器是一个对象,每个唯一的name 作为键。如果name 已经存在,请使用concat 将它们推送到数组中。否则,在累加器中创建一个新键并将其设置为当前对象。然后,使用Object.values() 将数组的值作为数组获取

const owners = [{name:"john",hasCar:!0,yearBought:2002},{name:"john",hasCar:!0,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:!0,yearBought:2018}];

const merged = owners.reduce((r, o) => {
  if(r[o.name])
    r[o.name].yearBought = [].concat(r[o.name].yearBought, o.yearBought)
  else
    r[o.name] = { ...o };
  return r;
},{})

console.log(Object.values(merged))

【讨论】:

    【解决方案2】:

    只需使用reduce:

    const owners = [{name:"john",hasCar:true,yearBought:2002},{name:"john",hasCar:true,yearBought:2005},{name:"mary",hasCar:true,yearBought:2015},{name:"john",hasCar:true,yearBought:2018}];
    
    const newOwners = Object.values(owners.reduce((acc, curr) => {
      acc[curr.name] = acc[curr.name] ? { ...acc[curr.name], yearBought: [].concat(acc[curr.name].yearBought, curr.yearBought) } : curr;
      return acc;
    }, {}));
    
    console.log(newOwners);

    【讨论】:

      【解决方案3】:

      我希望这有助于使用 PURE lodash 函数.. 它看起来干净且可读。

      var array = [{
        name: "john",
        hasCar: true,
        yearBought: 2002
      }, {
        name: "john",
        hasCar: true,
        yearBought: 2005
      }, {
        name: "mary",
        hasCar: true,
        yearBought: 2015
      }, {
        name: "john",
        hasCar: true,
        yearBought: 2018
      }]
      
      function mergeNames(arr) {
        return Object.values(_.chain(arr).groupBy('name').mapValues((g) => (_.merge(...g, {
          yearBought: _.map(g, 'yearBought')
        }))).value());
      }
      console.log(mergeNames(array));
      <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>

      谢谢:)

      【讨论】:

      • 这也会为mary 创建一个yearBought 数组
      • 我相信它应该在每种情况下都保持一致,即我们对yearBought 有一个或多个值。这样你就可以轻松管理了
      【解决方案4】:

      您可以使用唯一键(在您的情况下为name)对项目进行分组,然后映射组,并合并每个组中的项目:

      const { flow, partialRight: pr, groupBy, map, mergeWith, concat, isUndefined } = _
      
      const mergeDuplicates = (isCollected, key) => flow(
        pr(groupBy, key), // group by the unique key
        pr(map, group => mergeWith({}, ...group, 
          (o, s, k) => isCollected(k) && !isUndefined(o) ? concat(o, s) : s
        )) // merge each group to a new object
      )
      
      const owners = [{name:"john",hasCar:true,yearBought:2002},{name:"john",hasCar:true,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:true,yearBought:2018}]
      
      const isCollected = key => key === 'yearBought'
      
      const result = mergeDuplicates(isCollected, 'name')(owners)
      
      console.log(result)
      <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

      还有 lodash/fp 版本:

      const { flow, groupBy, map, mergeAllWith, cond, nthArg, concat } = _
      
      const mergeDuplicates = (isCollected, key) => flow(
        groupBy(key),
        map(mergeAllWith(cond([[
          flow(nthArg(2), isCollected),
          concat,
          nthArg(1)
        ]])))
      )
      
      const owners = [{name:"john",hasCar:!0,yearBought:2002},{name:"john",hasCar:!0,yearBought:2005},{name:"mary",hasCar:!0,yearBought:2015},{name:"john",hasCar:!0,yearBought:2018}]
      
      const isCollected = key => key === 'yearBought'
      
      const result = mergeDuplicates(isCollected, 'name')(owners)
      
      console.log(result)
      <script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-27
        • 1970-01-01
        • 1970-01-01
        • 2019-11-12
        • 2017-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多