困惑,循环遍历嵌套对象和做特定的计算

Confused, Looping over nested Object and doing specific calculations

本文关键字:计算 对象 循环 遍历 嵌套 困惑      更新时间:2023-09-26

卡住了!我有以下代码:

const hours = [
    {
        "workHour" : "8",
        "Item name 1" : 120,
        "Item name 2" : 149,
        "Item name 3" : 137
    },
    {
        "workHour" : "9",
        "Item name 1" : 134,
        "Item name 2" : 119,
        "Item name 3" : 144
    },
    {
        "workHour" : "10",
        "Item name 1" : 60,
        "Item name 2" : 86,
        "Item name 3" : 83
    },
];
const records = [
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours },
];
const result = {};
result.chart = [];
records.forEach((record) => {
   const items = [];
   record.statistics.forEach((hour) => {
      for (let key in hour) {
         if (key !== 'workHour') {
           items.push({
              key: hour[key]
           })
         }
      }
   });
   result.chart.push({
      date: record.date,
      items
   });
});
console.log(result);

我要做的是循环遍历记录数组中的每个项目,然后循环遍历每个记录的小时数,将每个项目的所有值相加,例如计算所有小时数的总和,我要得到的结果是:

array = [
  { 
    date: //record date,
    "Item name 1" : 314,
    "Item name 2" : 354,
    "Item name 3" : 364
  },
  { 
    date: //record date,
    "Item name 1" : 314,
    "Item name 2" : 354,
    "Item name 3" : 364
  },
  { 
    date: //record date,
    "Item name 1" : 314,
    "Item name 2" : 354,
    "Item name 3" : 364
  }
];

工时项键已知的工作示例:

const hours = [
{
    "workHour" : "8",
    "Item name 1" : 120,
    "Item name 2" : 149,
    "Item name 3" : 137
},
{
    "workHour" : "9",
    "Item name 1" : 134,
    "Item name 2" : 119,
    "Item name 3" : 144
},
{
    "workHour" : "10",
    "Item name 1" : 60,
    "Item name 2" : 86,
    "Item name 3" : 83
},

);

const records = [
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours },
];
const result = {};
result.records = [];
const calculate = (profits, key) =>
  profits
  .filter(profit => profit !== null)
  .reduce((prevVal, profitVal) => prevVal + profitVal[key], 0) || 0;
records.forEach((record) => {
   const items = [];
   const { statistics } = record;
   result.records.push({
      date: record.date,
      'Item name 1': calculate(statistics, 'Item name 1'),
      'Item name 2': calculate(statistics, 'Item name 2'),
      'Item name 3': calculate(statistics, 'Item name 3'),
   });
});
console.log(result);

打印:

records = [

{
      'Item name 1': 314,
      'Item name 2': 354,
      'Item name 3': 364,
   },
   {
      'Item name 1': 314,
      'Item name 2': 354,
      'Item name 3': 364,
   },
   {
      'Item name 1': 314,
      'Item name 2': 354,
      'Item name 3': 364,
   },
]

我相信这解决了您的要求,但我觉得还有更多。记录是否都具有相同的小时数?

我知道它有点密集,所以我添加了一些评论,我希望能阐明这是如何工作的。

const hours = [
  { "workHour" : "8", "Item name 1" : 120, "Item name 2" : 149, "Item name 3" : 137 },
  { "workHour" : "9", "Item name 1" : 134, "Item name 2" : 119, "Item name 3" : 144 },
  { "workHour" : "10", "Item name 1" : 60, "Item name 2" : 86, "Item name 3" : 83 }
];
const records = [
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours }
];
// ========================
// Using map()
// For each "record" return an object based on "record"
// ========================
var result = records.map(function(record){
  // ========================
  // Create the initial result that does not depend
  // on summing up the "statistics".
  //
  // We will pass this into the reduce() and it will be the
  // initial value of the accumulator
  // ========================
  var initialResult = {date: record.date};
  // ========================
  
  // ========================
  // Using reduce()
  // itterate over the interesting work items
  // summing up the hours
  // ========================
  var finalResult = record.statistics.reduce(function(acc, item){
    Object.keys(item)  // an array of keys in our item object
          .filter(function(key){ return key !== "workHour"; }) // remove this key
          .forEach(function(key) { acc[key] = (acc[key] || 0) + item[key] }); // for each remaining key, add its value to running total
    // ========================
    // return the running total accumulator for use against the next item
    // ========================
    return acc;
    // ========================
  }, initialResult);
  // ========================
  // ========================
  // return an object based on record but with accumulated data from the reduce()
  // this object becomes an item in the array ultimately returned by map()
  // ========================
  return finalResult;
  // ========================
});
// ========================
console.log(result)

下面是一个没有reduce的版本:

const hours = [
  { "workHour" : "8", "Item name 1" : 120, "Item name 2" : 149, "Item name 3" : 137 },
  { "workHour" : "9", "Item name 1" : 134, "Item name 2" : 119, "Item name 3" : 144 },
  { "workHour" : "10", "Item name 1" : 60, "Item name 2" : 86, "Item name 3" : 83 }
];
const records = [
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours },
   { date: new Date(), statistics: hours }
];
var result = records.map(function(record){
  var initialResult = {date: record.date};
  record.statistics.forEach(function(item){
    Object.keys(item)
          .filter(function(key){ return key !== "workHour"; })
          .forEach(function(key) { initialResult[key] = (initialResult[key] || 0) + item[key] });
  });
  return initialResult;
});
console.log(result)

如果问题解释正确,可以将for..of循环替换为.forEach(),使用计算的属性名[key]来设置推入items数组的对象的属性名

const hours = [{
  "workHour": "8",
  "Item name 1": 120,
  "Item name 2": 149,
  "Item name 3": 137
}, {
  "workHour": "9",
  "Item name 1": 134,
  "Item name 2": 119,
  "Item name 3": 144
}, {
  "workHour": "10",
  "Item name 1": 60,
  "Item name 2": 86,
  "Item name 3": 83
}, ];
const records = hours.map((hour, index) => ({
    date: new Date(),
    statistics: hours[index]
  }));
const result = {};
result.chart = [];
records.forEach((record, index) => {
  const items = [];
  for (let {statistics:hour} of [record]) {
    for (let key in hour) {
    if (key !== 'workHour') {
        items.push({
          [key]: hour[key] 
                 + (result.chart[index -1] 
                      && result.chart[index -1].hasOwnProperty("items") 
                    ? result.chart[index-1].items
                      .filter(obj => obj.hasOwnProperty(key))[0][key] 
                    : 0)          
        })
      }
    }
  };
  result.chart.push({
    date: record.date,
    items
  });
});
console.log(result);