javascript - 按两个元素和总和值对数组对象进行分组(Javascript)

标签 javascript arrays typescript object reduce

我有以下情况:

我有一个包含当前登录用户的所有约会的数组,如下所示:

 this.appointments = [  
{ 
 CreatedBy: "bob",
 Description: "smthng",
 EndTime: "2020-06-01T17:00:00.000Z",
 EndTimezone: null,
 Id: 3,
 IsAllDay: false,
 Client: "Steven",
 Location: "smthng",
 RecurrenceRule: "FREQ=DAILY;INTERVAL=1;COUNT=5;",
 StartTime: "2020-06-01T09:00:00.000Z",
 StartTimezone: null,
 Subject: "smthng",
 km: 88,
 week: 23,
 _id: "5ecc6f4a08c79c6328974699"
}, 
{ 
 CreatedBy: "bob",
 Description: "smthng",
 EndTime: "2020-06-08T10:30:00.000Z",
 EndTimezone: null,
 Id: 4,
 IsAllDay: false,
 Client: "Steven",
 Location: "smthng",
 RecurrenceRule: null,
 StartTime: "2020-06-08T10:00:00.000Z",
 StartTimezone: null,
 Subject: "smthng"  ,
 km: 88,
 week: 24,
 _id: "5ed450d299d5303bd0338a7f"
}
  ] 

我最终想要做的是按每周客户对阵列进行分组。因此,累积每个客户一周的所有预约时间和公里数(使用 dayjs 库)。这是我现在拥有的 .reduce 函数,它仅按客户端对数组进行分组,但还不是每周:

this.appointments.reduce(function (res, value) {
  let diff = dayjs(value.EndTime).diff(dayjs(value.StartTime), "hour",true) % 60;
  let count;

  if(value.RecurrenceRule != null) {
    count =  parseInt(value.RecurrenceRule.split("COUNT=")[1]);
    if(value.RecurrenceException){
    if(value.RecurrenceException.match(/,/g) ) {
      if(value.RecurrenceException.match(/,/g).length == 0) {
        console.log(value.RecurrenceException.match(/,/g).length);
        count = count -1;
      }
    } else if(value.RecurrenceException && value.RecurrenceException.match(/,/g).length == 1) {
      console.log(value.RecurrenceException.match(/,/g).length);      
      count = count -2;
    } else if(value.RecurrenceException && value.RecurrenceException.match(/,/g).length == 2) {
      console.log(value.RecurrenceException.match(/,/g).length);
      count = count -3;
    } else
    if(value.RecurrenceException && value.RecurrenceException.match(/,/g).length == 3) {
       count = count -4;
    };
  }
  }
  else if(value.RecurrenceRule == null) {
       count = 1;
  }
  if (!res[value.Client]) {
    res[value.Client] = {

      week: value.week,
      km: value.km * count,
      Client: value.Client,
      count: count,
      difference: diff * count
    };
    result.push(res[value.Client]);


  } else {
    res[value.Client].km += value.km * count;
    res[value.Client].difference += diff * count;
  }

  return res;
}, {});

遇到这种情况我该怎么办? 现在的输出是,它不是创建两行(第 23 周和第 24 周),而是对 Steven 在第 23 周的所有约会进行求和,这是不正确的,因为另一周发生了 0.5 小时。

{Client: "Steven"
count: 5
difference: 40.5
km: 528
week: 23}

所以理想的输出是:

{
Client: "Steven"
count: 5
difference: 40
km: 440
week: 23 
},

{
Client: "Steven"
count: 1
difference: 0.5
km: 88
week: 24
}

只要客户不同,您就可以拥有具有相同周数的行。

我希望我说得清楚,如果您需要更多背景信息,请提及

最佳答案

基于@ajai的答案(并首先使用他的输入进行比较),希望能够为您提供所需的内容(并使用reduce)。

const data = [  
  { 
   CreatedBy: "bob",
   Description: "smthng",
   EndTime: "2020-06-01T17:00:00.000Z",
   EndTimezone: null,
   Id: 3,
   IsAllDay: false,
   Client: "Steven",
   Location: "smthng",
   RecurrenceRule: "FREQ=DAILY;INTERVAL=1;COUNT=5;",
   StartTime: "2020-06-01T09:00:00.000Z",
   StartTimezone: null,
   Subject: "smthng",
   km: 88,
   week: 23,
   _id: "5ecc6f4a08c79c6328974699"
  }, 
  { 
   CreatedBy: "bob",
   Description: "smthng",
   EndTime: "2020-06-08T10:30:00.000Z",
   EndTimezone: null,
   Id: 4,
   IsAllDay: false,
   Client: "Steven",
   Location: "smthng",
   RecurrenceRule: null,
   StartTime: "2020-06-08T10:00:00.000Z",
   StartTimezone: null,
   Subject: "smthng"  ,
   km: 88,
   week: 24,
   _id: "5ed450d299d5303bd0338a7f"
  },
  { 
   CreatedBy: "bob",
   Description: "smthng",
   EndTime: "2020-06-01T17:00:00.000Z",
   EndTimezone: null,
   Id: 3,
   IsAllDay: false,
   Client: "Steven",
   Location: "smthng",
   RecurrenceRule: "FREQ=DAILY;INTERVAL=1;COUNT=5;",
   StartTime: "2020-06-01T09:00:00.000Z",
   StartTimezone: null,
   Subject: "smthng",
   km: 40,
   week: 23,
   _id: "5ecc6f4a08c79c6328974699"
  },
  { 
   CreatedBy: "bob",
   Description: "smtng",
   EndTime: "2020-06-01T17:00:00.000Z",
   EndTimezone: null,
   Id: 3,
   IsAllDay: false,
   Client: "ajai",
   Location: "smthng",
   RecurrenceRule: "FREQ=DAILY;INTERVAL=1;COUNT=5;",
   StartTime: "2020-06-01T09:00:00.000Z",
   StartTimezone: null,
   Subject: "smthng",
   km: 88,
   week: 23,
   _id: "5ecc6f4a08c79c6328974699"
  }
]    
  

const result = Object.values(data.reduce((aggObj, item) => {
  const stringID = `${item.Client}_${item.week}`;
  const diff = (new Date(item.EndTime) - new Date(item.StartTime))/(1000*60*60);
  const RecurrenceObj = item.RecurrenceRule ?
    item.RecurrenceRule.split(";").map(a => {
      //console.log(a)
      return a.split("=") || ["_", null];          
    }).reduce((aggObj, [key,val]) => {
      aggObj[key] = val;
      return aggObj;
    })
    : {COUNT: 1};
    
  if (aggObj[stringID]){
    aggObj[stringID].km += (item.km * RecurrenceObj.COUNT);
    aggObj[stringID].count += parseInt(RecurrenceObj.COUNT);
    aggObj[stringID].difference += (diff * RecurrenceObj.COUNT);
  }
  else {  
    aggObj[stringID] = {
      Client: item.Client,
      km: item.km * RecurrenceObj.COUNT,
      count: parseInt(RecurrenceObj.COUNT),
      difference: diff * RecurrenceObj.COUNT,
      week: item.week
    };
  }
  return aggObj;
}, {}));

/*
for(var i=0;i<=data.length-1;i++){
   let pos = result.findIndex(el=> `${el.Client}-${el.week}`==`${data[i].Client}-${data[i].week}`)
   if(pos==-1){
     result.push({Client: data[i]['Client'],count: 1,difference: 0,km: data[i]['km'],week: data[i]['week']})
   }else{
     result[pos]['count'] = result[pos]['count'] + 1;
     result[pos]['km'] = result[pos]['km'] + data[i]['km'];
   }
}
*/
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

输出:

[
  {
    "Client": "Steven",
    "km": 640,
    "count": 10,
    "difference": 80,
    "week": 23
  },
  {
    "Client": "Steven",
    "km": 88,
    "count": 1,
    "difference": 0.5,
    "week": 24
  },
  {
    "Client": "ajai",
    "km": 440,
    "count": 5,
    "difference": 40,
    "week": 23
  }
]

现在输入您的确切信息:

const data = [  
  { 
   CreatedBy: "bob",
   Description: "smthng",
   EndTime: "2020-06-01T17:00:00.000Z",
   EndTimezone: null,
   Id: 3,
   IsAllDay: false,
   Client: "Steven",
   Location: "smthng",
   RecurrenceRule: "FREQ=DAILY;INTERVAL=1;COUNT=5;",
   StartTime: "2020-06-01T09:00:00.000Z",
   StartTimezone: null,
   Subject: "smthng",
   km: 88,
   week: 23,
   _id: "5ecc6f4a08c79c6328974699"
  }, 
  { 
   CreatedBy: "bob",
   Description: "smthng",
   EndTime: "2020-06-08T10:30:00.000Z",
   EndTimezone: null,
   Id: 4,
   IsAllDay: false,
   Client: "Steven",
   Location: "smthng",
   RecurrenceRule: null,
   StartTime: "2020-06-08T10:00:00.000Z",
   StartTimezone: null,
   Subject: "smthng"  ,
   km: 88,
   week: 24,
   _id: "5ed450d299d5303bd0338a7f"
  }
]    
  

const result = Object.values(data.reduce((aggObj, item) => {
  const stringID = `${item.Client}_${item.week}`;
  const diff = (new Date(item.EndTime) - new Date(item.StartTime))/(1000*60*60);
  const RecurrenceObj = item.RecurrenceRule ?
    item.RecurrenceRule.split(";").map(a => {
      //console.log(a)
      return a.split("=") || ["_", null];
    }).reduce((aggObj, [key,val]) => {
      aggObj[key] = val;
      return aggObj;
    })
    : {COUNT: 1};
    
  if (aggObj[stringID]){
    aggObj[stringID].km += (item.km * RecurrenceObj.COUNT);
    aggObj[stringID].count += parseInt(RecurrenceObj.COUNT);
    aggObj[stringID].difference += (diff * RecurrenceObj.COUNT);
  }
  else {  
    aggObj[stringID] = {
      Client: item.Client,
      km: item.km * RecurrenceObj.COUNT,
      count: parseInt(RecurrenceObj.COUNT),
      difference: diff * RecurrenceObj.COUNT,
      week: item.week
    };
  }
  return aggObj;
}, {}));

/*
for(var i=0;i<=data.length-1;i++){
   let pos = result.findIndex(el=> `${el.Client}-${el.week}`==`${data[i].Client}-${data[i].week}`)
   if(pos==-1){
     result.push({Client: data[i]['Client'],count: 1,difference: 0,km: data[i]['km'],week: data[i]['week']})
   }else{
     result[pos]['count'] = result[pos]['count'] + 1;
     result[pos]['km'] = result[pos]['km'] + data[i]['km'];
   }
}
*/
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

输出:

[
  {
    "Client": "Steven",
    "km": 440,
    "count": 5,
    "difference": 40,
    "week": 23
  },
  {
    "Client": "Steven",
    "km": 88,
    "count": 1,
    "difference": 0.5,
    "week": 24
  }
]

关于javascript - 按两个元素和总和值对数组对象进行分组(Javascript),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62133063/

相关文章:

Javascript 脚本元素集内部文本

javascript - 使用 angularjs 从下拉列表中删除重复项

javascript - 如何在nodejs,JavaScript中的字符后包含字符串

javascript - ES6 : Populate object value with a value from another object when ID is present

javascript - 基于文件扩展名的多个 Webpack 构建

c++ - 分配具有相同值的多维 std::array 的简单方法?

python - 防止 numpy 创建多维数组

javascript - Angular2 在 ngFor 循环中绑定(bind)事件/DOM

javascript - 使用 date-fns 将日期解析为 UTC 的正确方法

node.js - Cassandra 的类型 ORM