正在寻找一种更“实用”的方式来实现这一目标...
我有一个看起来像这样的产品对象(请注意重复的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
?
答案 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 /随需调用,其中每个对象都以给定的属性名称存储。如果字典中已经存在一个条目,则使用合并功能将现有条目与新条目合并,否则将新条目简单地存储到对象中。