如何根据以下数据建模与目标对象类似的对象?如果 ES6 中存在简写,那么它会更合适。
数据样本包含人员及其收集的元素的信息。Max和Carol收集了具有不同值的相同石头。如果发生这种情况,则应将其作为新元素推送到我们的目标对象中。
示例数据
let people = [{
"id": 1, // Person Id
"name": "John", // Name of person
"date": "2017-5-27", // Date
"totalAssets": 500, // Sum of total (gems collected)
"gems": [{ // Gems collected from forest
"total": 500, // totalCollected * value
"value": 100, // Value of one gem (Ruby = 100)
"totalCollected": 5, // Total number
"gemName": "Ruby", // Gem name
"gemCode": "GEM001" // Gem code
}]
}, {
"id": 2,
"name": "Max",
"date": "2017-5-28",
"totalAssets": 1300, // TotalAssets = Emerald.total + Moonstone.total
"gems": [{
"total": 900,
"value": 150,
"totalCollected": 6,
"gemName": "Emerald",
"gemCode": "GEM002"
}, {
"total": 400,
"value": 250,
"totalCollected": 2,
"gemName": "Moonstone",
"gemCode": "GEM003"
}]
}, {
"id": 3,
"name": "Carol",
"date": "2017-5-29",
"totalAssets": 2900,
"gems": [{
"total": 1500,
"value": 150,
"totalCollected": 10,
"gemName": "Emerald",
"gemCode": "GEM002"
}, {
"total": 1000,
"value": 200,
"totalCollected": 5,
"gemName": "Moonstone",
"gemCode": "GEM003"
},
{
"total": 400,
"value": 100,
"totalCollected": 4,
"gemName": "Ruby",
"gemCode": "GEM001"
}
]
}]
计算总计
computeTotal = () => { //Mock target object function
// Return target object
"totalAssets": 4800, //Total assets of all people
"gemsValueTotal":[{
"gemName": "Ruby",
"value": 100,
"totalC0llected":9,
"total": 900,
},
{
"gemName": "Emerald",
"value": 150,
"totalC0llected":16,
"total": 2400,
},
{
"gemName": "MoonStone",
"value": 200,
"totalC0llected":5,
"total": 1000,
},
{
"gemName": "MoonStone", // Value changed so push as new item in object
"value": 250,
"totalC0llected":2,
"total": 500,
}
]
}
我通过这种方式找到了一些解决方案。
aggregateGems(data) {
this.rows = [];
let totalCollected = 0;
let totalvalue = 0;
return data.filter((item) => {
item.gems.map(d => {
let model: any = {};
let totalAssets: number = 0;
totalCollected += parseInt(d.totalCollected);
totalvalue += parseInt(d.total);
model.gemname = d.gemName;
model.value = d.value;
model.totalCollected = totalCollected;
model.totalValue = totalValue;
this.rows.push(model);
debugger
});
},
);
}
最佳答案
您可以使用 Array.reduce
来完成此操作功能,与 Array.forEach
合作功能。
// this will save the indexes of the gemNames and value in the output array (so you don't have to search for the index all of the time)
let gemNameValueIndex = {};
// this will reduce the people array in a new object, receiving the new object and the next person on each iteration
let totals = people.reduce( (current, person) => {
// and for each person we need to iterate the gems
person.gems.forEach( gem => {
// each gem increases the total value
current.totalAssets += gem.total;
let key = gem.gemName + gem.value;
let idx;
if ((idx = gemNameValueIndex[key]) === undefined) {
// no matching gem found, so add the index
current.gemsValueTotal.push( {
gemName: gem.gemName,
value: gem.value,
totalCollected: gem.totalCollected,
total: gem.total
} );
// mark the index so it can be looked up for next iterations
gemNameValueIndex[key] = current.gemsValueTotal.length - 1;
return;
}
// update the already found index with the new totals
current.gemsValueTotal[idx].totalCollected += gem.totalCollected;
current.gemsValueTotal[idx].total += gem.total;
});
return current;
}, { totalAssets: 0, gemsValueTotal: [] } );
您的totals
对象现在将包含您正在查找的数据(您可以在下面的代码片段中尝试一下)。
gemNameValueIndex
将包含每个值的 gem 作为键以及生成的总对象中的索引(但该对象的存在只是为了避免循环 gemsValueTotal 中所有添加的 gem ,以根据我们需要比较的 gemName 和每个 gem 的值查找索引)
let people = [{
"id": 1, // Person Id
"name": "John", // Name of person
"date": "2017-5-27", // Date
"totalAssets": 500, // Sum of total (gems collected)
"gems": [{ // Gems collected from forest
"total": 500, // totalCollected * value
"value": 100, // Value of one gem (Ruby = 100)
"totalCollected": 5, // Total number
"gemName": "Ruby", // Gem name
"gemCode": "GEM001" // Gem code
}]
}, {
"id": 2,
"name": "Max",
"date": "2017-5-28",
"totalAssets": 1300, // TotalAssets = Emerald.total + Moonstone.total
"gems": [{
"total": 900,
"value": 150,
"totalCollected": 6,
"gemName": "Emerald",
"gemCode": "GEM002"
}, {
"total": 400,
"value": 250,
"totalCollected": 2,
"gemName": "Moonstone",
"gemCode": "GEM003"
}]
}, {
"id": 3,
"name": "Carol",
"date": "2017-5-29",
"totalAssets": 2900,
"gems": [{
"total": 1500,
"value": 150,
"totalCollected": 10,
"gemName": "Emerald",
"gemCode": "GEM002"
}, {
"total": 1000,
"value": 200,
"totalCollected": 5,
"gemName": "Moonstone",
"gemCode": "GEM003"
},
{
"total": 400,
"value": 100,
"totalCollected": 4,
"gemName": "Ruby",
"gemCode": "GEM001"
}
]
}];
// this will save the indexes of the gemNames and value in the output array (so you don't have to search for the index all of the time)
let gemNameValueIndex = {};
// this will reduce the people array in a new object, receiving the new object and the next person on each iteration
let totals = people.reduce( (current, person) => {
// and for each person we need to iterate the gems
person.gems.forEach( gem => {
// each gem increases the total value
current.totalAssets += gem.total;
let key = gem.gemName + gem.value;
let idx;
if ((idx = gemNameValueIndex[key]) === undefined) {
// no matching gem found, so add the index
current.gemsValueTotal.push( {
gemName: gem.gemName,
value: gem.value,
totalCollected: gem.totalCollected,
total: gem.total
} );
// mark the index so it can be looked up for next iterations
gemNameValueIndex[key] = current.gemsValueTotal.length - 1;
return;
}
// update the already found index with the new totals
current.gemsValueTotal[idx].totalCollected += gem.totalCollected;
current.gemsValueTotal[idx].total += gem.total;
});
return current;
}, { totalAssets: 0, gemsValueTotal: [] } );
console.log( totals );
关于javascript - 如何找到项目的总和并动态创建新对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44427242/