Javascript 如何找到项目的总和并动态创建新对象?

Javascript 如何找到项目的总和并动态创建新对象?,javascript,object,ecmascript-6,Javascript,Object,Ecmascript 6,如何根据以下数据对类似于目标对象的对象进行建模?如果ES6中存在任何缩写,那么它将更合适 数据示例包含人员及其收集的项目的信息。people Max和Carol收集了具有不同值的相同石头。如果发生这种情况,应将其作为新项目推送到目标对象中 样本数据 let people = [{ "id": 1, // Person Id "name": "John", // Name of person "date":

如何根据以下数据对类似于目标对象的对象进行建模?如果ES6中存在任何缩写,那么它将更合适

数据示例包含人员及其收集的项目的信息。people 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
       });
     },
   );
 }
您可以使用该函数,并与该函数配合使用

// 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
将包含每个值的gems作为一个键,并在生成的total对象中包含索引(但该对象仅用于避免在gemnameValueTotal中循环所有添加的gems,以根据gemName和每个gem的值查找索引,我们需要进行比较)

let people=[{
“id”:1,//个人id
“姓名”:“John”,//姓名
“日期”:“2017-5-27”,//日期
“totalAssets”:500,//总计(收集的宝石)
“宝石”:[{//从森林中收集的宝石
“总计”:500,//totalCollected*值
“值”:100,//一颗宝石的值(Ruby=100)
“totalCollected”:5,//总数
“gemName”:“Ruby”,//Gem name
“gemCode”:“GEM001”//Gem代码
}]
}, {
“id”:2,
“名称”:“最大值”,
“日期”:“2017-5-28”,
“totalAssets”:1300,//totalAssets=Emerald.total+Moonstone.total
“宝石”:[{
“总数”:900,
“价值”:150,
“总计收集”:6,
“宝石名”:“翡翠”,
“gemCode”:“GEM002”
}, {
“总数”:400,
“价值”:250,
“总计收集”:2,
“gemName”:“月光石”,
“gemCode”:“GEM003”
}]
}, {
“id”:3,
“姓名”:“卡罗尔”,
“日期”:“2017-5-29”,
“总资产”:2900,
“宝石”:[{
“总数”:1 500,
“价值”:150,
“总计收集”:10,
“宝石名”:“翡翠”,
“gemCode”:“GEM002”
}, {
“总数”:1000,
“价值”:200,
“总计收集”:5,
“gemName”:“月光石”,
“gemCode”:“GEM003”
},
{
“总数”:400,
“价值”:100,
“总计收集”:4,
“gemName”:“Ruby”,
“gemCode”:“GEM001”
}
]
}];
//这将在输出数组中保存gemNames和value的索引(因此您不必一直搜索索引)
让gemNameValueIndex={};
//这将减少新对象中的人员数组,在每次迭代中接收新对象和下一个人
让总数=人。减少((当前,人)=>{
//对于每个人,我们需要迭代这些宝石
person.gems.forEach(gem=>{
//每颗宝石都会增加总价值
流动资产总额+=创业板总额;
让key=gem.gemName+gem.value;
让idx;
if((idx=gemNameValueIndex[key])==未定义){
//找不到匹配的gem,请添加索引
当前.gemsValueTotal.push({
gemName:gem.gemName,
价值:gem.value,
totalCollected:gem.totalCollected,
总数:gem.total
} );
//标记索引,以便在下一次迭代中查找它
gemNameValueIndex[键]=current.gemValueTotal.length-1;
回来
}
//用新总数更新已找到的索引
current.gemValueTotal[idx].totalCollected+=gem.totalCollected;
当前.gemValueTotal[idx].total+=gem.total;
});
回流;
},{totalAssets:0,GemValueTotal:[]});

控制台日志(总计)你试过什么吗?@31piy谢谢你的回复。请查看更新的。谢谢。这正是我想要的。