在javascript中合并部分重复的数组(lodash)

时间:2019-05-01 06:35:12

标签: javascript arrays lodash

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

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

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

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

5 个答案:

答案 0 :(得分: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))

答案 1 :(得分:0)

您可以使用普通的javascript来代替loadash

尝试一下:

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

let tmpList = [];
let result = [];
for (var i = 0; i < owners.length; i++) {
  if (tmpList.indexOf(owners[i].name) == -1) {
    tmpList.push(owners[i].name);
    result.push(owners[i]);
    result[result.length-1].yearBought = [result[result.length-1].yearBought];
    for (var j = 0; j < owners.length; j++) {
      if (i != j && owners[i].name == owners[j].name) {
        result[result.length-1].yearBought.push(owners[owners.length-1].yearBought);
      }
    }
  }
}
console.log(result);

答案 2 :(得分:0)

只需使用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 :(得分:0)

我希望此帮助使用 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>

谢谢:)

答案 4 :(得分:0)

您可以使用唯一键(在您的情况下为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>