[英]How to create nested object based on dynamic keys
我需要將一些數據轉換為特殊格式。 棘手的部分是,它需要被動態鍵分組和嵌套。 由於原始數據持平。
這是一些簡化的示例數據:
const data = [
{
category: 'Classic',
price: 1,
order: '1233-ABC'
currency: 'EUR',
},
{
category: 'Classic',
price: 2,
order: '1234-ABC'
currency: 'EUR',
},
{
category: 'Modern',
price: 3,
order: '1235-ABC'
currency: 'USD',
},
{
category: 'Classic',
price: 4,
order: '1236-ABC'
currency: 'EUR',
},
{
category: 'Modern',
price: 5,
order: '1237-ABC'
currency: 'EUR',
},
{
category: 'Classic',
price: 6,
order: '1238-ABC'
currency: 'USD',
},
{
category: 'Modern',
price: 7,
order: '1239-ABC'
currency: 'USD',
}
];
現在我想定義分組和聚合。
例如:
grouping = ['category'];
sum = ['price'];
因此它應該分組category
鍵並總結所有price
鍵條目。
//預期輸出
[{
category: 'Classic',
price: 13
}, {
category: 'Modern',
price: 15
}]
我使用reduce進行了這項工作。
這是代碼:
let groupingsField = ['category'];
let aggregateField = ['price']
let [group, ...rest] = groupingsField
let [sum, ...noone] = aggregateField
const groupedData = data.reduce((acc, current) => {
acc.push({
[group]: current[group],
[sum]: data.filter(item => item[group] === current[group])
.map(el => el[sum])
.reduce((total, current) => total + current)
})
return acc
}, [])
.reduce((acc, current) => {
const x = acc.find(item => item[group] === current[group])
return !x ? acc.concat([current]) : acc
}, [])
但是,我需要分組是動態的,如果那里有超過1個值,它應該創建嵌套的sub
數據集。 應該可以添加多個分組。
//示例2
grouping = ['category', 'currency'];
sum = ['price'];
//預期輸出
[{
category: 'Classic',
price: 13,
sub: [{
currency: 'EUR',
price: 7
}, {
currency: 'USD',
price: 6
}]
}, {
category: 'Modern',
price: 15,
sub: [{
currency: 'EUR',
price: 9
}, {
currency: 'USD',
price: 10
}]
}]
因此,如果我要為分組添加另一個鍵
grouping = ['category', 'currency', 'something'];
它應該是三層深的nestes。
{
category: 'Modern',
price: 15,
sub: [{
currency: 'EUR',
price: 9,
sub: [{
someting: ...
price: ...
}]
}]
}
但是,我無法理解這一點,如何根據groupings
動態添加嵌套。 我想我需要一些遞歸。
會喜歡這方面的幫助!
謝謝您的幫助! 然而,經過一段時間的睡眠后,我想出了自己的解決方案:
groups = ['category', 'currency']; // this can be dynamic
sum = ['price'];
function createGroup (groups, data, sum, childNode = 'sub') {
let [primaryGroup, ...rest] = groups;
let groupedData = data.reduce((acc, current) => {
let chunk = {
[primaryGroup]: current[primaryGroup],
[sum]: data.filter(item => item[primaryGroup] === current[primaryGroup])
.map(el => el[sum])
.reduce((total, current) => total + current),
...(rest.length > 0 ? {[childNode]: createGroup(rest, data)} : {})
}
acc.push(chunk)
return acc
}, [])
.reduce((acc, current) => {
const x = acc.find(item => item[primaryGroup] === current[primaryGroup])
return !x ? acc.concat([current]) : acc
}, [])
return groupedData;
}
嗯......這確實是一個挑戰,但我認為它有效...也許不是最花哨的方式,但我想它會做。
var newArr = [];
var MyObj = {};
var MyObj2 = {};
for( i = 0; i < data.length; i++){
if (data[i].category + '|' + data[i].currency in MyObj) MyObj[data[i].category + '|' + data[i].currency] += data[i].price;
else MyObj[data[i].category + '|' + data[i].currency] = data[i].price;
}
for (var key in MyObj) {
let keyArr=-1;
let split_key = key.split("|");
for( i = 0; i < newArr.length; i++){
console.log(newArr[i].category + '/' +split_key[0] + i);
if (newArr[i].category == split_key[0]) {
keyArr=i;
break;
}
}
if (keyArr<0){
MyObj2['category'] = split_key[0];
MyObj2['price'] = MyObj[key];
MyObj2['sub'] = [{currency: split_key[1], price: MyObj[key]}];
newArr.push(MyObj2);
}else{
newArr[keyArr]['price']+=MyObj[key];
newArr[keyArr]['sub'].push({currency: split_key[1], price: MyObj[key]});
}
MyObj2={};
}
console.log(newArr);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.