繁体   English   中英

按键分组的对象数组的总和值并返回到新的数组数组中

[英]Sum values of array of object grouped by keys and return into a new array of arrays

我需要对按两个属性分组的所有值求和: "date""zona" 特别是,我想将"date"翻译成星期几,并按它分组。 对于"zona"我想按“zona 1”、“zona 2”、“zona 3”等分组。

预期结果:

[dayOfWeek, zoneId, value];

[
   [0, 0, something],
   [0, 1, something],
   ...
   [0, 9, something],
   [1, 0, something],
   ...
   [6, 9, something]
]

我已经做了类似的事情(这里是jsfiddle):

数据初始化:

const data = [
  {
     "date": "2017/12/31",
     "ALL.new users": 298,
     "ALL.returning users": 12528,
     "zona 1.new users": 189,
     "zona 1.returning users": 3422,
     "zona 10.new users": 18,
     "zona 10.returning users": 2767,
     "zona 2.new users": 11,
     "zona 2.returning users": 1216,
     "zona 3.new users": 20,
     "zona 3.returning users": 3175,
     "zona 4.new users": 5,
     "zona 4.returning users": 1465,
     "zona 5.new users": 3,
     "zona 5.returning users": 1102,
     "zona 6.new users": 20,
     "zona 6.returning users": 2223,
     "zona 7.new users": 2,
     "zona 7.returning users": 1063,
     "zona 8.new users": 25,
     "zona 8.returning users": 1093,
     "zona 9.new users": 3,
     "zona 9.returning users": 1507
  }, {...}
];

const zoneMapping = {
   "Zone 1": 0,
   "Zone 2": 1,
   "Zone 3": 2,
   "Zone 4": 3,
   "Zone 5": 4,
   "Zone 6": 5,
   "Zone 7": 6,
   "Zone 8": 7,
   "Zone 9": 8,
   "Zone 10": 9
};

const dayMapping = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

功能:

let tempSeriesData = [];     

data.forEach(
   (item) => {
       const date = (new Date(item.date)).getDay();

       Object.entries(item).forEach(([key, value]) => {
           if (key !== "date" && key !== "ALL.new users" && key !== "ALL.returning users" && !key.includes("new users")) {
               let tempYValue = key.slice(0, 7).replace(".", "");
               tempYValue = tempYValue.replace("a", "e");
               const yValue = tempYValue.charAt(0).toLocaleUpperCase() + tempYValue.slice(1)
               const dataValue = Number(value);
               const element = [
                   date,
                   zoneMapping[yValue],
                   dataValue
               ];

               const existingElement = tempSeriesData.find(el => el[0] === element[0] && el[1] === element[1]);
               if (existingElement) {
                   existingElement[2] += element[2];
               }
               else {
                   tempSeriesData.push(element);
               }            
           }
       });
   }
);

有了这个函数,我可以获得我想要的东西,但我正在寻找一种新方法来做同样的事情,也许使用 map()、reduce 或其他东西,因为我想改进这些方法的使用。

提前感谢您的回答。

其实还好代码是明确的,它做了它应该做的。 如果我们真的想重构它,为了清晰起见,我会使用对象,然后在数组中进行转换。 另外我会使用 map/reduce 而不是全局 var + forEach 循环。

const parser = (item) => {
  const date = (new Date(item.date)).getDay();
  myItem = Object.entries(item).flatMap(([key, value]) => {
    key = key.split(/[\s.]+/) // split the key on SPACE and DOT at the same time
    // Maybe I misunderstand the IF from before but this works right now.
    return key[2] === "returning" ? [{ day: date, zone: key[1] - 1, value: Number(value) }] : []
  })
  return myItem
}

// upsert adds elements to the object if new or update existing
const upSert = (acc, { value, ...r }) => {
  key = JSON.stringify(r) // Since it is a nested map, we make our life easier with unique keys.
  acc[key] = (acc[key] || { ...r, value: 0 }); // if null initialize
  return (acc[key].value += value, acc) // update in place
}

const toValueArray = (data) => {
  return Object.values(data).map(d => Object.values(d))
}

//This could be already populated from a previous run
// Probably comming as a prop to a component
seriesData = {}

myTs = data.flatMap(parser)
  .reduce(upSert, seriesData)

const finalSeriesData = toValueArray(myTs)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM