在具有特定条件的 lodash 中添加和组合对象数组中的重复项

Add and combine duplicates in array of objects with lodash with specific conditions

假设我有一个排序的对象数组,如下所示:

[
  {name: 'item1', quantity: 5},
  {name: 'item1', quantity: 8},
  {name: 'item2', quantity: 6},
  {name: 'item2', quantity: 3},
  {name: 'item3', quantity: 1},
  {name: 'item3', quantity: 1},
]

我想将具有 quantities > 1 的项目的值相加并将它们合并,这样我得到:

[
  {name: 'item1', quantity: 13},
  {name: 'item2', quantity: 9},
  {name: 'item3', quantity: 1},
  {name: 'item3', quantity: 1},
]

是否有快速的单个或链式 lodash 方法可以实现这一点?我正在考虑使用 _.map 但它不会给你上一个项目,所以我必须使用 _.map 范围之外的变量来保留该值。看看我是否可以用 lodash 做到这一点,因为我已经将它用于其他方法,而不是编写额外的代码行。

如果无法满足额外条件,则必须合并并添加所有项目。

您可以使用 Array.prototype.forEach() , for 循环

var arr = [
  {name: 'item1', quantity: 5},
  {name: 'item1', quantity: 8},
  {name: 'item2', quantity: 6},
  {name: 'item2', quantity: 3},
  {name: 'item3', quantity: 1},
  {name: 'item3', quantity: 1},
];

var res = [];

arr.forEach(function(item, index) {
  if (res.length === 0 
      || !res.some(function(elem) {return elem.name === item.name}) 
      || item["quantity"] === 1 ) {
    res.push(item)
  } else {
    for (var i = 0; i < res.length; i++) {
      if (res[i]["name"] === item["name"] 
          && (res[i]["quantity"] !== 1 && item["quantity"] !== 1)) {
        res[i]["quantity"] += item["quantity"]
      }
    }
  }
});

document.querySelector("pre").textContent = JSON.stringify(res, null, 2)
<pre></pre>

这是一个纯粹的 lodash-ian 解决方案:)
它使用 chainreducetoPairsmap 和 1 个临时变量来完成这项工作。

items = [
  {name: 'item1', quantity: 5},
  {name: 'item1', quantity: 8},
  {name: 'item2', quantity: 6},
  {name: 'item2', quantity: 3},
  {name: 'item3', quantity: 1},
  {name: 'item3', quantity: 1}
];

summary = _.chain(items).reduce(function(acc, i) {
  if (i.quantity > 0) {
    acc[i.name] = (acc[i.name] || 0) + i.quantity;
  }
  return acc;
}, {}).toPairs().map(function(x) {
  var tmp = {};
  tmp[x[0]] = x[1];
  return tmp;
}).value();

console.log(JSON.stringify(summary));
// Outputs:  [{"item1":13},{"item2":9},{"item3":2}]

另一种简单的解决方案Javascript,只有一个循环。

var data = [{ name: 'item1', quantity: 5 }, { name: 'item1', quantity: 8 }, { name: 'item2', quantity: 6 }, { name: 'item2', quantity: 3 }, { name: 'item3', quantity: 1 }, { name: 'item3', quantity: 1 }],
    combined = function (array) {
        var r = [];
        array.forEach(function (a, i) {
            if (a.quantity === 1) {
                r.push(a);
                return;
            }
            if (!this[a.name]) {
                this[a.name] = { name: a.name, quantity: 0 };
                r.push(this[a.name]);
            }
            this[a.name].quantity += a.quantity;
        }, {});
        return r;
    }(data);

document.write('<pre>' + JSON.stringify(combined, 0, 4) + '</pre>');

这是我仅使用 lodash 的尝试:

var source = [
  {name: 'item1', quantity: 5},
  {name: 'item1', quantity: 8},
  {name: 'item2', quantity: 6},
  {name: 'item2', quantity: 3},
  {name: 'item3', quantity: 1},
  {name: 'item3', quantity: 1},
];

var predicate = function (e) {
  return e.quantity > 1;
};
var result = _.chain(source)
  .filter(predicate)
  .groupBy(function (e) {
    return e.name;
  })
  .map(function (group) {
    return _.reduce(group, function (current, next) {
      return {
        name: next.name,
        quantity: current.quantity + next.quantity
      };
    });
  })
  .union(_.filter(source, function (e) {
    return !predicate(e);
  }))
  .value();

document.getElementById("output").textContent = JSON.stringify(result, 0, 2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.6.1/lodash.min.js"></script>
<pre id="output"></pre>

不确定这是否是最有效的方法,因为我对 lodash 不是很熟悉。基本上,这个想法是这样的:

  1. 获取数量 > 1 的元素
  2. 按名称分组
  3. 为每个名字生成总和
  4. 与数量 <= 1 的元素并集

Fiddle