Javascript:根据属性值折叠对象数组,对数量属性求和,保留最新的

时间:2019-05-16 15:34:56

标签: javascript functional-programming

正在寻找一种更“实用”的方式来实现这一目标...

我有一个看起来像这样的产品对象(请注意重复的skuid

"products": [
    {
      "skuid": "B1418",
      "name": "Test Product 1",
      "price": 7,
      "lastOrderedDate": 20181114,
      "quantity": 2
    },{
      "skuid": "B3446",
      "name": "Test Product 2",
      "price": 6,
      "lastOrderedDate": 20190114,
      "quantity": 2
    },{
      "skuid": "B1418",
      "name": "Test Product 1",
      "price": 7,
      "lastOrderedDate": 20180516,
      "quantity": 5
    },{
      "skuid": "B3446",
      "name": "Test Product 2",
      "price": 6,
      "lastOrderedDate": 20180411,
      "quantity": 11
    }
]

我想创建一个新数组,每个不同的skuid都具有一个对象,但是所有quantity值的SUMS 都保留最新的lastOrderedDate

最终结果如下:

"products": [
    {
      "skuid": "B1418",
      "name": "Test Product 1",
      "price": 7,
      "lastOrderedDate": 20181114,
      "quantity": 7
    },{
      "skuid": "B3446",
      "name": "Test Product 2",
      "price": 6,
      "lastOrderedDate": 20190114,
      "quantity": 13
    }
]

我可以用一堆forEach和if来做到这一点,但我想学习一种更简洁的方法。也许是排序,然后是reduce

3 个答案:

答案 0 :(得分:2)

您可以按照以下步骤进行操作:

  • 使用reduce()创建一个对象,其键将具有唯一的作用,而值将使该对象skuid处于第一个状态
  • 在数组上使用forEach,并在对象创建的对象中增加相应对象的quantity属性。
  • 使用Object.values()获取一个数组。

const products = [ { "skuid": "B1418", "name": "Test Product 1", "price": 7, "lastOrderedDate": 20181114, "quantity": 2 },{ "skuid": "B3446", "name": "Test Product 2", "price": 6, "lastOrderedDate": 20190114, "quantity": 2 },{ "skuid": "B1418", "name": "Test Product 1", "price": 7, "lastOrderedDate": 20180516, "quantity": 5 },{ "skuid": "B3446", "name": "Test Product 2", "price": 6, "lastOrderedDate": 20180411, "quantity": 11 } ]

const res = products.reduce((ac,a) => (!ac[a.skuid] ? ac[a.skuid] = a : '',ac),{})

products.forEach(x => res[x.skuid].quantity += x.quantity)

console.log(Object.values(res))

答案 1 :(得分:2)

您可以使用Map并在以后获得所有值作为结果集。

const
    getGrouped = (m, o) => {
        var item = m.get(o.skuid);
        if (!item) return m.set(o.skuid, Object.assign({}, o));
        if (item.lastOrderedDate < o.lastOrderedDate) item.lastOrderedDate = o.lastOrderedDate;
        item.quantity += o.quantity;
        return m;
    };


var data = { products: [{ skuid: "B1418", name: "Test Product 1", price: 7, lastOrderedDate: 20181114, quantity: 2 }, { skuid: "B3446", name: "Test Product 2", price: 6, lastOrderedDate: 20190114, quantity: 2 }, { skuid: "B1418", name: "Test Product 1", price: 7, lastOrderedDate: 20180516, quantity: 5 }, { skuid: "B3446", name: "Test Product 2", price: 6, lastOrderedDate: 20180411, quantity: 11 }] },
    result = Array.from(data.products
        .reduce(getGrouped, new Map)
        .values()
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)

您可以这样做:

const DATA = [
    {
      "skuid": "B1418",
      "name": "Test Product 1",
      "price": 7,
      "lastOrderedDate": 20181114,
      "quantity": 2
    },{
      "skuid": "B3446",
      "name": "Test Product 2",
      "price": 6,
      "lastOrderedDate": 20190114,
      "quantity": 2
    },{
      "skuid": "B1418",
      "name": "Test Product 1",
      "price": 7,
      "lastOrderedDate": 20180516,
      "quantity": 5
    },{
      "skuid": "B3446",
      "name": "Test Product 2",
      "price": 6,
      "lastOrderedDate": 20180411,
      "quantity": 11
    }
];



const mergeStrategy = {
  quantity: (a, b) => a + b,
  lastOrderedDate: (a, b) => Math.max(a, b)
}

const mergeByStrategy = strat => a => b => {
  const c = Object.assign({}, a, b);
  return Object.keys(strat).reduce((acc, k) => {
    acc[k] = strat[k](a[k], b[k]);
    return acc;
  }, c);
}

const groupByWith = prop => merge => xs => xs.reduce((acc, x) => {
  if (acc[x[prop]] === void 0) { acc[x[prop]] = x; }
  else { acc[x[prop]] = merge(acc[x[prop]])(x); }
  return acc;
}, {});




const mergeFunc = mergeByStrategy(mergeStrategy);
const groupData = groupByWith('skuid')(mergeFunc);

console.log(Object.values(groupData(DATA)))

mergeStrategy定义如何合并某些属性。您可以在此处定义任意数量的属性/功能。

mergeByStrategy函数首先采用策略(请参见上文),然后合并两个对象。请注意,它以咖喱形式接收对象。它创建两个对象的浅拷贝,并根据给定的策略对其进行修改。这样可以确保您的原始数据仍然完整。

groupByWith函数使用一个属性名称,一个合并函数和一个对象数组,并创建一个字典/ POJO / hashmap /随需调用,其中每个对象都以给定的属性名称存储。如果字典中已经存在一个条目,则使用合并功能将现有条目与新条目合并,否则将新条目简单地存储到对象中。