如何使用lodash通过键连接两个大小不同的对象数组

时间:2018-10-05 15:25:13

标签: javascript lodash

Stocks: [{
    PRN: 1,
    PID: 1,
    Qty: 3,
    SlNos: [1, 2, 3]
}, {
    PRN: 1,
    PID: 2,
    Qty: 4,
    SlNos: [10, 11, 12, 13]
}, {
    PRN: 2,
    PID: 1,
    Qty: 3,
    SlNos: [4, 5, 6]
}, {
    PRN: 2,
    PID: 2,
    Qty: 4,
    SlNos: [14, 15, 16, 17]
}]

我希望此数组与Lodash一起使用

Stocks: [{
    PID: 1,
    Qty: 6,
    SlNos: [1, 2, 3, 4, 5, 6]
}, {
    PID: 2,
    Qty: 4,
    SlNos: [10, 11, 12, 13, 14, 15, 16, 17]
}]

1 个答案:

答案 0 :(得分:0)

这是_lodash的解决方案:

var stocks = [{ PRN: 1, PID: 1, Qty: 3, SlNos: [1, 2, 3] }, { PRN: 1, PID: 2, Qty: 4, SlNos: [10, 11, 12, 13] }, { PRN: 2, PID: 1, Qty: 3, SlNos: [4, 5, 6] }, { PRN: 2, PID: 2, Qty: 4, SlNos: [14, 15, 16, 17] }]

const result = _.reduce(stocks, (r, {PRN, ...c}) => {
   let _c = _.find(r, {'PID': c.PID})
   if(_c)
     _c = _.mergeWith(_c, c, (ov, sv, k) => _.includes(['Qty','SlNos'], k) ? _.isArray(sv) ? (ov || []).concat(sv) : _.isNumber(sv) ? sv + (ov || 0) : sv : ov)
   else
     r.push(c)
   return r
}, [])

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

我们将reducemergeWith(实际上是这里的主要内容)一起使用,再加上一点includes

这是一个没有lodash的解决方案,可以解决这个问题:

var stocks = [{ PRN: 1, PID: 1, Qty: 3, SlNos: [1, 2, 3] }, { PRN: 1, PID: 2, Qty: 4, SlNos: [10, 11, 12, 13] }, { PRN: 2, PID: 1, Qty: 3, SlNos: [4, 5, 6] }, { PRN: 2, PID: 2, Qty: 4, SlNos: [14, 15, 16, 17] }]

const result = stocks.reduce((r, c) => {
  _c = r.find(x => x.PID === c.PID)
  if (_c) {
    _c.PID = c.PID
    _c.Qty = _c.Qty + c.Qty
    _c.SlNos = _c.SlNos ? _c.SlNos.concat(c.SlNos) : c.SlNos
  } else {
    r.push(!delete(c.PRN) || c)
  }
  return r
}, [])

console.log(result)

这个想法是使用reduce和第一个find,如果我们已经通过PID使用该对象,那么如果不插入最终数组,则将这些值相加。由于我们要遍历每条记录,因此逻辑可以在一个循环中解决问题。