具有reduce功能的汇总/计数数组



我是JS的新手,并且在能够为里程应用程序汇总Google电子表格数据数组方面遇到了障碍。

我正在尝试计算由员工 ID 和日期驱动的里程数,但尚未找到在线资源来使用 reduce/filter 执行此级别的功能。


var records = [
["2019-08-26", emp1, 111],
["2019-08-26", emp2, 79],
["2019-09-02", emp1, 111],
["2019-09-02", emp2, 59],
["2019-09-02", emp3, 22],
["2019-09-05", emp3, 26],
["2019-09-02", emp1, 12],
["2019-09-05", emp3, 50],
["2019-09-02", emp2, 49],
["2019-09-05", emp1, 69],
["2019-09-02", emp1, 42],
["2019-09-05", emp3, 21],
["2019-09-02", emp2, 101],
["2019-09-05", emp3, 78],
["2019-09-02", emp3, 35],
["2019-09-05", emp1, 47]
]

我已经尝试了 for 循环和减少/映射组合,但我无法让代码以我们想要的方式返回数据。最好的尝试是使用reduce功能,所以我认为我走在正确的轨道上?我也尝试只映射一个单独数组中的日期进行匹配,但不确定这是否会使其更加复杂。

日期、员工和里程会不断变化,因此我必须使用的方法必须是动态的,以适应未来的员工、日期和数百条记录。

我做错了什么?

var summary = records.reduce(function(total, employee) {
total[employee[0]] = total[employee[0]] || []
total[employee[0]].push({
date: employee[0], 
eid: employee[1],
miles: employee[2]      
}) 
return total                                                              
},{})

更新:我被要求在计算按天和员工驾驶的里程后确定"第一次旅行"。我尝试将Math.max()Math.min()嵌入到答案中的代码中,但我认为这不是正确的方法。关于我应该如何处理这个新发展的任何想法?

[
{date: "2019-08-26", employee: emp1, miles: 111, firstTrip: 111},
{date: "2019-08-26", employee: emp2, miles: 79, firstTrip: 79},
{date: "2019-09-02", employee: emp1, miles: 65, firstTrip: 12},
{date: "2019-09-02", employee: emp2, miles: 209, firstTrip: 49},
{date: "2019-09-02", employee: emp3, miles: 57, firstTrip:22}, 
etc
]

由于Google Sheet数据,我在Google AppScript(GAS(环境中工作。任何帮助将不胜感激。

在你的尝试中,你正在做的是用date like key和该date like values中的所有不同条目来索引一个对象,如下所示:

{
"2019-08-26": [
{date: "2019-08-26", employee: emp1, miles: 111},
{date: "2019-08-26", employee: emp2, miles: 79}
],
"2019-09-02": [
{date: "2019-09-02", employee: emp1, miles: 111},
{date: "2019-09-02", employee: emp2, miles: 59},
{date: "2019-09-02", employee: emp3, miles: 22}
],
etc...
}

如果我明白你想做什么,你需要传递第二个参数来reduce数组[],而不是对象{}

在每次迭代之后,您必须检查是否已经存在具有给定日期和员工的元素。如果没有,请推动该元素,如果是,则将英里添加到给定对象。

代码将如下所示:

var summary = records.reduce( (total,record) => {
var index = total.findIndex( s => s.date == record[0] && s.employee == record[1] );
if( index == -1 ){
total.push( {date: record[0], employee: record[1], miles: record[2]} );
}else{
total[ index ].miles += record[2];
}
return total;
},[]);

你会得到这个结果:

[
{"date":"2019-08-26","employee":emp1,"miles":111},
{"date":"2019-08-26","employee":emp2,"miles":79},
{"date":"2019-09-02","employee":emp1,"miles":165},
{"date":"2019-09-02","employee":emp2,"miles":209},
{"date":"2019-09-02","employee":emp3,"miles":57},
{"date":"2019-09-05","employee":emp3,"miles":175},
{"date":"2019-09-05","employee":emp1,"miles":116}
]

编辑:对于Google APPS脚本,请尝试使用以下内容:

var summary = records.reduce( function(total,record){
var index = -1;
total.forEach( function(s,i){
if( s.date == record[0] && s.employee == record[1] ) index = i;
});
if( index == -1 ){
total.push( {date: record[0], employee: record[1], miles: record[2]} );
}else{
total[ index ].miles += record[2];
}
return total;
},[]);