聚合一个对象,其中每个键的值是一个对象数组
Aggregate an object in which the value for each key is an array of objects
我正在使用 Underscore 和 Lodash 按日期对数组进行分组。到目前为止一切正常,我得到一个对象,其中每个键的值都是一个对象数组,如下所示:
{
"april": [
{
"quantity": "200",
"date": "05/04/2020, 23:43",
"price": "150",
"product": "Washing Machine",
"provider": "LG",
"total": 30000
},
{
"quantity": "1000",
"date": "10/04/2020, 00:35",
"price": "800",
"product": "Television",
"provider": "Samsung",
"total": 800000
},
{
"quantity": "3000",
"date": "10/04/2020, 18:02",
"price": "2",
"product": "Computer",
"provider": "Sony",
"total": 600000
},
{
"quantity": "1000",
"date": "10/04/2020, 18:03",
"price": "300",
"product": "Bluetooth Speaker",
"provider": "Sony",
"total": 300000
}
],
"march": [
{
"quantity": "400",
"date": "18/03/2020, 23:47",
"price": "230",
"product": "Home Theatre",
"provider": "Bose",
"total": 92000
}
],
"february": [
{
"quantity": "550",
"date": "07/02/2020, 23:52",
"price": "300",
"product": "Printer",
"provider": "Epson",
"total": 165000
},
{
"quantity": "750",
"date": "07/02/2020, 23:52",
"price": "200",
"product": "Television",
"provider": "Panasonic",
"total": 150000
}
]
}
我想知道谁是每个月总计最大的供应商(例如,4 月份是索尼,两次不同的采购总额为 900,000 美元),但我一直无法访问和汇总数据。我知道 Whosebug 中有很多类似的问题,但令人惊讶的是我无法找到与这种数据结构相关的任何类似问题。
任何帮助将不胜感激。
您可以结合使用 map()
and reduce()
来实现您想要的效果,例如:
let data = {
april: [{
quantity: "200",
date: "05/04/2020, 23:43",
price: "150",
product: "Washing Machine",
provider: "LG",
total: 30000,
},
{
quantity: "1000",
date: "10/04/2020, 00:35",
price: "800",
product: "Television",
provider: "Samsung",
total: 800000,
},
{
quantity: "3000",
date: "10/04/2020, 18:02",
price: "2",
product: "Computer",
provider: "Sony",
total: 600000,
},
{
quantity: "1000",
date: "10/04/2020, 18:03",
price: "300",
product: "Bluetooth Speaker",
provider: "Sony",
total: 300000,
},
],
march: [{
quantity: "400",
date: "18/03/2020, 23:47",
price: "230",
product: "Home Theatre",
provider: "Bose",
total: 92000,
}, ],
february: [{
quantity: "550",
date: "07/02/2020, 23:52",
price: "300",
product: "Printer",
provider: "Epson",
total: 165000,
},
{
quantity: "750",
date: "07/02/2020, 23:52",
price: "200",
product: "Television",
provider: "Panasonic",
total: 150000,
},
],
};
let aggregatedData = Object.keys(data).map((month) =>
data[month].reduce((acc, current, i) => {
let existing = acc.find((o) => o.provider === current.provider);
if (existing) {
existing.total += current.total;
} else {
acc[i] = { provider: current.provider, total: current.total };
}
return acc;
}, [])
);
let biggestProviders = aggregatedData.map((data) =>
data.reduce((p, c) => (c.total > p.total ? c : p))
);
console.log(biggestProviders);
console.log(biggestProviders.map(o => o.provider));
根据数据的键,我们获取每个月的公司数据数组并减少对象,如果提供者已经存在则累加它们的总数。然后我们通过比较谁的总数最高来映射和减少结果数据,然后我们只映射最终结果以获得提供者的名称。
边缘情况: 我还注意到这种方法的一个小问题,即在有两个提供商的总数完全相同的情况下,所以我已经制作了一个快速片段,它只是 return 一组恰好具有相同总数的提供者数组。如果我们不考虑这一点,我们可能 return 只是最大的提供商之一,总计:
let data = {
april: [{
quantity: "200",
date: "05/04/2020, 23:43",
price: "150",
product: "Washing Machine",
provider: "LG",
total: 30000,
},
{
quantity: "1000",
date: "10/04/2020, 00:35",
price: "800",
product: "Television",
provider: "Samsung",
total: 900000,
},
{
quantity: "3000",
date: "10/04/2020, 18:02",
price: "2",
product: "Computer",
provider: "Sony",
total: 600000,
},
{
quantity: "1000",
date: "10/04/2020, 18:03",
price: "300",
product: "Bluetooth Speaker",
provider: "Sony",
total: 300000,
},
],
march: [{
quantity: "400",
date: "18/03/2020, 23:47",
price: "230",
product: "Home Theatre",
provider: "Bose",
total: 92000,
}, ],
february: [{
quantity: "550",
date: "07/02/2020, 23:52",
price: "300",
product: "Printer",
provider: "Epson",
total: 165000,
},
{
quantity: "750",
date: "07/02/2020, 23:52",
price: "200",
product: "Television",
provider: "Panasonic",
total: 165000,
},
],
};
let aggregatedData = Object.keys(data).map((month) =>
data[month].reduce((acc, current, i) => {
let existing = acc.find((o) => o.provider === current.provider);
if (existing) {
existing.total += current.total;
} else {
acc[i] = {
provider: current.provider,
total: current.total
};
}
return acc;
}, [])
);
let biggestProviders = aggregatedData.map((data) =>
data.reduce((p, c) => {
if (p.length === 0) return p.concat(c);
if (c.total === p[0].total) {
p.push(c);
} else {
p = c.total > p[0].total ? Array.of(c) : Array.of(...p);
}
return p;
}, [])
);
console.log(biggestProviders);
您可以使用临时对象(下面的 resultObj)在遍历列表时累计每个提供商每月的总数。
跟踪每月最高总价的对象示例:
var resultObj = {
"max" : {
"num" : 0, // current max total goes here
"provider" : "" // provider with max total goes here
},
"maxObject" : {}, // max items for each month stored here
getMax : function() {
// returns current max object to be added to maxObject[month]
return { "provider": this.max.provider, "total": this.max.num };
},
"reset" : function() { // reset max
this.max.num = 0;
this.max.provider = ""
},
"createKey" : function(month) { // create month key
if(!this.hasOwnProperty(month))
this[month] = {};
}
};
以及遍历对象数组的函数:
function getMaxValue() {
for(let month in obj) { // for each month in the object
resultObj.reset(); // reset max
resultObj.createKey(month); // create key for month in resultObj
obj[month].forEach(function(el) { // for each object within month
if(resultObj[month][el.provider]) { // if the provider exists as a key
resultObj[month][el.provider] += el.total;
} else { // provider doesn't yet exist
resultObj[month][el.provider] = el.total;
}
// if current total is greater than current max (for given month)
if(resultObj[month][el.provider] > resultObj.max.num) {
resultObj.max.num = resultObj[month][el.provider];
resultObj.max.provider = el.provider;
}
});
resultObj.maxObject[month] = resultObj.getMax(); // generate result for month
}
return resultObj.maxObject; // return the result object
}
检查并测试如下:
var obj = {
"april": [
{
"quantity": "200",
"date": "05/04/2020, 23:43",
"price": "150",
"product": "Washing Machine",
"provider": "LG",
"total": 30000
},
{
"quantity": "1000",
"date": "10/04/2020, 00:35",
"price": "800",
"product": "Television",
"provider": "Samsung",
"total": 800000
},
{
"quantity": "3000",
"date": "10/04/2020, 18:02",
"price": "2",
"product": "Computer",
"provider": "Sony",
"total": 600000
},
{
"quantity": "1000",
"date": "10/04/2020, 18:03",
"price": "300",
"product": "Bluetooth Speaker",
"provider": "Sony",
"total": 300000
}
],
"march": [
{
"quantity": "400",
"date": "18/03/2020, 23:47",
"price": "230",
"product": "Home Theatre",
"provider": "Bose",
"total": 92000
}
],
"february": [
{
"quantity": "550",
"date": "07/02/2020, 23:52",
"price": "300",
"product": "Printer",
"provider": "Epson",
"total": 165000
},
{
"quantity": "750",
"date": "07/02/2020, 23:52",
"price": "200",
"product": "Television",
"provider": "Panasonic",
"total": 150000
}
]
};
var resultObj = {
"max" : {
"num" : 0,
"provider" : ""
},
"maxObject" : {},
"getMax" : function() {
return { "provider": this.max.provider, "total": this.max.num };
},
"reset" : function() {
this.max.num = 0;
this.max.provider = "";
},
"createKey" : function(month) {
if(!this.hasOwnProperty(month))
this[month] = {};
}
};
function getMaxValue() {
for(let month in obj) {
resultObj.reset();
resultObj.createKey(month);
obj[month].forEach(function(el) {
if(resultObj[month][el.provider]) {
resultObj[month][el.provider] += el.total;
} else {
resultObj[month][el.provider] = el.total;
}
if(resultObj[month][el.provider] > resultObj.max.num) {
resultObj.max.num = resultObj[month][el.provider];
resultObj.max.provider = el.provider;
}
});
resultObj.maxObject[month] = resultObj.getMax();
}
return resultObj.maxObject;
}
var maxValues = getMaxValue(); // receives an object
console.log( maxValues ); // prints the all the results
console.log("\nmax for April:");
console.log( maxValues.april ); // prints results for April
console.log("\nNow to check resultObj:");
console.log( resultObj ); // prints the whole temp object
我正在使用 Underscore 和 Lodash 按日期对数组进行分组。到目前为止一切正常,我得到一个对象,其中每个键的值都是一个对象数组,如下所示:
{
"april": [
{
"quantity": "200",
"date": "05/04/2020, 23:43",
"price": "150",
"product": "Washing Machine",
"provider": "LG",
"total": 30000
},
{
"quantity": "1000",
"date": "10/04/2020, 00:35",
"price": "800",
"product": "Television",
"provider": "Samsung",
"total": 800000
},
{
"quantity": "3000",
"date": "10/04/2020, 18:02",
"price": "2",
"product": "Computer",
"provider": "Sony",
"total": 600000
},
{
"quantity": "1000",
"date": "10/04/2020, 18:03",
"price": "300",
"product": "Bluetooth Speaker",
"provider": "Sony",
"total": 300000
}
],
"march": [
{
"quantity": "400",
"date": "18/03/2020, 23:47",
"price": "230",
"product": "Home Theatre",
"provider": "Bose",
"total": 92000
}
],
"february": [
{
"quantity": "550",
"date": "07/02/2020, 23:52",
"price": "300",
"product": "Printer",
"provider": "Epson",
"total": 165000
},
{
"quantity": "750",
"date": "07/02/2020, 23:52",
"price": "200",
"product": "Television",
"provider": "Panasonic",
"total": 150000
}
]
}
我想知道谁是每个月总计最大的供应商(例如,4 月份是索尼,两次不同的采购总额为 900,000 美元),但我一直无法访问和汇总数据。我知道 Whosebug 中有很多类似的问题,但令人惊讶的是我无法找到与这种数据结构相关的任何类似问题。 任何帮助将不胜感激。
您可以结合使用 map()
and reduce()
来实现您想要的效果,例如:
let data = {
april: [{
quantity: "200",
date: "05/04/2020, 23:43",
price: "150",
product: "Washing Machine",
provider: "LG",
total: 30000,
},
{
quantity: "1000",
date: "10/04/2020, 00:35",
price: "800",
product: "Television",
provider: "Samsung",
total: 800000,
},
{
quantity: "3000",
date: "10/04/2020, 18:02",
price: "2",
product: "Computer",
provider: "Sony",
total: 600000,
},
{
quantity: "1000",
date: "10/04/2020, 18:03",
price: "300",
product: "Bluetooth Speaker",
provider: "Sony",
total: 300000,
},
],
march: [{
quantity: "400",
date: "18/03/2020, 23:47",
price: "230",
product: "Home Theatre",
provider: "Bose",
total: 92000,
}, ],
february: [{
quantity: "550",
date: "07/02/2020, 23:52",
price: "300",
product: "Printer",
provider: "Epson",
total: 165000,
},
{
quantity: "750",
date: "07/02/2020, 23:52",
price: "200",
product: "Television",
provider: "Panasonic",
total: 150000,
},
],
};
let aggregatedData = Object.keys(data).map((month) =>
data[month].reduce((acc, current, i) => {
let existing = acc.find((o) => o.provider === current.provider);
if (existing) {
existing.total += current.total;
} else {
acc[i] = { provider: current.provider, total: current.total };
}
return acc;
}, [])
);
let biggestProviders = aggregatedData.map((data) =>
data.reduce((p, c) => (c.total > p.total ? c : p))
);
console.log(biggestProviders);
console.log(biggestProviders.map(o => o.provider));
根据数据的键,我们获取每个月的公司数据数组并减少对象,如果提供者已经存在则累加它们的总数。然后我们通过比较谁的总数最高来映射和减少结果数据,然后我们只映射最终结果以获得提供者的名称。
边缘情况: 我还注意到这种方法的一个小问题,即在有两个提供商的总数完全相同的情况下,所以我已经制作了一个快速片段,它只是 return 一组恰好具有相同总数的提供者数组。如果我们不考虑这一点,我们可能 return 只是最大的提供商之一,总计:
let data = {
april: [{
quantity: "200",
date: "05/04/2020, 23:43",
price: "150",
product: "Washing Machine",
provider: "LG",
total: 30000,
},
{
quantity: "1000",
date: "10/04/2020, 00:35",
price: "800",
product: "Television",
provider: "Samsung",
total: 900000,
},
{
quantity: "3000",
date: "10/04/2020, 18:02",
price: "2",
product: "Computer",
provider: "Sony",
total: 600000,
},
{
quantity: "1000",
date: "10/04/2020, 18:03",
price: "300",
product: "Bluetooth Speaker",
provider: "Sony",
total: 300000,
},
],
march: [{
quantity: "400",
date: "18/03/2020, 23:47",
price: "230",
product: "Home Theatre",
provider: "Bose",
total: 92000,
}, ],
february: [{
quantity: "550",
date: "07/02/2020, 23:52",
price: "300",
product: "Printer",
provider: "Epson",
total: 165000,
},
{
quantity: "750",
date: "07/02/2020, 23:52",
price: "200",
product: "Television",
provider: "Panasonic",
total: 165000,
},
],
};
let aggregatedData = Object.keys(data).map((month) =>
data[month].reduce((acc, current, i) => {
let existing = acc.find((o) => o.provider === current.provider);
if (existing) {
existing.total += current.total;
} else {
acc[i] = {
provider: current.provider,
total: current.total
};
}
return acc;
}, [])
);
let biggestProviders = aggregatedData.map((data) =>
data.reduce((p, c) => {
if (p.length === 0) return p.concat(c);
if (c.total === p[0].total) {
p.push(c);
} else {
p = c.total > p[0].total ? Array.of(c) : Array.of(...p);
}
return p;
}, [])
);
console.log(biggestProviders);
您可以使用临时对象(下面的 resultObj)在遍历列表时累计每个提供商每月的总数。
跟踪每月最高总价的对象示例:
var resultObj = {
"max" : {
"num" : 0, // current max total goes here
"provider" : "" // provider with max total goes here
},
"maxObject" : {}, // max items for each month stored here
getMax : function() {
// returns current max object to be added to maxObject[month]
return { "provider": this.max.provider, "total": this.max.num };
},
"reset" : function() { // reset max
this.max.num = 0;
this.max.provider = ""
},
"createKey" : function(month) { // create month key
if(!this.hasOwnProperty(month))
this[month] = {};
}
};
以及遍历对象数组的函数:
function getMaxValue() {
for(let month in obj) { // for each month in the object
resultObj.reset(); // reset max
resultObj.createKey(month); // create key for month in resultObj
obj[month].forEach(function(el) { // for each object within month
if(resultObj[month][el.provider]) { // if the provider exists as a key
resultObj[month][el.provider] += el.total;
} else { // provider doesn't yet exist
resultObj[month][el.provider] = el.total;
}
// if current total is greater than current max (for given month)
if(resultObj[month][el.provider] > resultObj.max.num) {
resultObj.max.num = resultObj[month][el.provider];
resultObj.max.provider = el.provider;
}
});
resultObj.maxObject[month] = resultObj.getMax(); // generate result for month
}
return resultObj.maxObject; // return the result object
}
检查并测试如下:
var obj = {
"april": [
{
"quantity": "200",
"date": "05/04/2020, 23:43",
"price": "150",
"product": "Washing Machine",
"provider": "LG",
"total": 30000
},
{
"quantity": "1000",
"date": "10/04/2020, 00:35",
"price": "800",
"product": "Television",
"provider": "Samsung",
"total": 800000
},
{
"quantity": "3000",
"date": "10/04/2020, 18:02",
"price": "2",
"product": "Computer",
"provider": "Sony",
"total": 600000
},
{
"quantity": "1000",
"date": "10/04/2020, 18:03",
"price": "300",
"product": "Bluetooth Speaker",
"provider": "Sony",
"total": 300000
}
],
"march": [
{
"quantity": "400",
"date": "18/03/2020, 23:47",
"price": "230",
"product": "Home Theatre",
"provider": "Bose",
"total": 92000
}
],
"february": [
{
"quantity": "550",
"date": "07/02/2020, 23:52",
"price": "300",
"product": "Printer",
"provider": "Epson",
"total": 165000
},
{
"quantity": "750",
"date": "07/02/2020, 23:52",
"price": "200",
"product": "Television",
"provider": "Panasonic",
"total": 150000
}
]
};
var resultObj = {
"max" : {
"num" : 0,
"provider" : ""
},
"maxObject" : {},
"getMax" : function() {
return { "provider": this.max.provider, "total": this.max.num };
},
"reset" : function() {
this.max.num = 0;
this.max.provider = "";
},
"createKey" : function(month) {
if(!this.hasOwnProperty(month))
this[month] = {};
}
};
function getMaxValue() {
for(let month in obj) {
resultObj.reset();
resultObj.createKey(month);
obj[month].forEach(function(el) {
if(resultObj[month][el.provider]) {
resultObj[month][el.provider] += el.total;
} else {
resultObj[month][el.provider] = el.total;
}
if(resultObj[month][el.provider] > resultObj.max.num) {
resultObj.max.num = resultObj[month][el.provider];
resultObj.max.provider = el.provider;
}
});
resultObj.maxObject[month] = resultObj.getMax();
}
return resultObj.maxObject;
}
var maxValues = getMaxValue(); // receives an object
console.log( maxValues ); // prints the all the results
console.log("\nmax for April:");
console.log( maxValues.april ); // prints results for April
console.log("\nNow to check resultObj:");
console.log( resultObj ); // prints the whole temp object