我有一个包含不同对象的数组,其中每个对象都是一个订单。 看起来像这样:
array = [
{
doc : {
date: "2017-03-06T16:48:23.080Z",
products:[
{
product: "Product 1",
number: 3
},
{
product: "Product 2",
number: 2
}
]
}
},
{
doc : {
date: "2017-03-07T16:48:23.080Z",
products:[
{
product: "Product 2",
number: 10
},
{
product: "Product 3",
number: 1
}
]
}
}
]
我希望能够获取这些数据并将其推送到新数组中,其中每个数据都有一个日期属性(按日期分组),以及一个产品嵌套数组,它对不同的订单进行分组(按产品分组)。像这样:
array = [
{
date: 'Date X',
products: [
{
product: 'product 1',
units: 3
},
{
product: 'product 2',
units: 2
}
]
},
{
date: 'Date Y',
products: [
{
product: 'product 2',
units: 10
},
{
product: 'product 3',
units: 1
}
]
}
]
你会怎么做?我已经尝试过Lodash试图重用一些旧代码,但到目前为止没有运气。可以用forEach吗?
答案 0 :(得分:1)
使用lodash和ES6的解决方案:
// Remove unnecesary .doc properties
let arrayWithoutDoc = _.map(array, el => el.doc);
// Group by dates to single object
let grouped = _.groupBy(arrayWithoutDoc, el => el.date);
// Convert object to requested format
let result = _.map(grouped, (value, date) => ({
date: date,
products: sumProductsUnits(
_.flatMap(value, el => el.products)
)
}));
// Function for grouping unique products with sum of units
function sumProductsUnits(products) {
var productGroups = _.groupBy(products, productObj => productObj.product);
return _.map(productGroups, (productGroup, productName) => ({
product: productName,
units: productGroup.reduce((sum, val) => sum + val.number, 0)
}))
}
我假设,units
等于原始对象中的number
。
result
包含:
[
{
"date":"2017-03-06T16:48:23.080Z",
"products":[
{
"product":"Product 1",
"units":3
},
{
"product":"Product 2",
"units":2
}
]
},
{
"date":"2017-03-07T16:48:23.080Z",
"products":[
{
"product":"Product 2",
"units":10
},
{
"product":"Product 3",
"units":1
}
]
}
]
答案 1 :(得分:1)
您可以对哈希表使用嵌套方法,该方法反映日期和产品以便于访问。
var array = [{ doc: { date: "2017-03-06T16:48:23.080Z", products: [{ product: "Product 1", number: 3 }, { product: "Product 2", number: 2 }] } }, { doc: { date: "2017-03-07T16:48:23.080Z", products: [{ product: "Product 2", number: 10 }, { product: "Product 3", number: 1 }] } }],
result = [],
hash = { _: result };
array.forEach(function (a) {
var date = a.doc.date.slice(0, 10),
temp = hash;
if (!temp[date]) {
temp[date] = { _: [] };
temp._.push({ date: date, products: temp[date]._ });
}
temp = temp[date];
a.doc.products.forEach(function (b) {
if (!temp[b.product]) {
temp[b.product] = { product: b.product, units: 0 };
temp._.push(temp[b.product]);
}
temp[b.product].units += b.number;
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 2 :(得分:0)
一个简单的算法是将结果存储到一个数组中,并在每次迭代时检查该数组中是否存在日期:
function groupByDate(array) {
var result = [];
for (var i = 0; i < array.length; i++) {
var doc = array[i].doc;
// try to find an element in the resulting array with the same date
var group = result.find(function(element) {
// Note: this will do string comparison up to the millisecond.
// If you want to group by days, months or years you might need
// to parse the dates here
return element.doc.date == doc.date;
}) || null;
if (group == null) {
// No element with the specified date was found in the resulting array =>
// we create a new one and append it
group = {
doc: {
date: doc.date,
products: []
}
};
result.push(group);
}
// push the input products to the group
group.doc.products.push.apply(group.doc.products, doc.products);
}
return result;
}
然后像这样使用这个函数:
var array = ... the input array from your question ...
var reuslt = groupByDate(array);