JavaScript对象数组分组和求和

JavaScript对象数组分组和求和

问题描述:

我的任务是创建一个时间表表格,它将显示每个客户端每天工作的小时数。该表看起来应该像下面的代码片段:JavaScript对象数组分组和求和

table, td, th { 
 
      border: 1px solid black; 
 
     }
<div> 
 
    <table id="testTable" class="table"> 
 
    <tr> 
 
     <th>Client name</th> 
 
     <th>Monday</th> 
 
     <th>Tuesday</th> 
 
     <th>Wednesday</th> 
 
     <th>Thursday</th> 
 
     <th>Friday</th> 
 
     <th>Saturday</th> 
 
     <th>Sunday</th> 
 
    </tr> 
 
    <tr> 
 
     <td>client1</td> 
 
     <td>0</td> 
 
     <td>5</td> 
 
     <td>3</td> 
 
     <td>2</td> 
 
     <td>3</td> 
 
     <td>0</td> 
 
     <td>0</td> 
 
    </tr> 
 
    <tr> 
 
     <td>client2</td> 
 
     <td>4</td> 
 
     <td>1</td> 
 
     <td>4</td> 
 
     <td>2</td> 
 
     <td>1</td> 
 
     <td>0</td> 
 
     <td>0</td> 
 
    </tr> 
 
    </table> 
 
</div>
我遇到的问题是,查询来填充表所需的时间表项目后,我不确定如何在客户端名称的诊断项目和星期几。检索到的阵列将类似于此:

timesheetItems = [ 
 
    timesheetItem = { 
 
     clientName: client1, 
 
     hoursWorked: 2, 
 
     day: Monday 
 
    }, 
 
    timesheetItem = { 
 
     clientName: client1, 
 
     hoursWorked: 3, 
 
     day: Monday 
 
    }, 
 
    timesheetItem = { 
 
     clientName: client1, 
 
     hoursWorked: 4, 
 
     day: Wednesday 
 
    }, 
 
    timesheetItem = { 
 
     clientName: client2, 
 
     hoursWorked: 4, 
 
     day: Monday 
 
    } 
 
    
 
    ];
分组阵列应该组的所有时间表项目为每个客户端的一个对象,这一周的每一天键包含的时间的总和就职于那天。最终的阵列应该是这个样子:

groupedArray = { 
 
    Client1 = { 
 
    Mon: 5, 
 
    tues: 3, 
 
    ... 
 
    sun: 0 
 
    }, 
 
    client2 = { 
 
    mon:2, 
 
    ... 
 
    }, 
 
    client3 = { 
 
    ... 
 
    }, 
 
    ... 
 
}

因此,如果任何人都可以提出如何去分组时间表项目数组,这样的结果会像上面的代码片段,这样我就可以轻松地从分组数组中循环来填充表格,这将非常有帮助。 谢谢。

+0

[阵列#减少(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) – Xotic750

要聚合的阵列可以使用reduce

const groupedArray = timesheetItems.reduce((prev, curr) => { 
    if (!prev[curr.clientName]) { 
     prev[curr.clientName] = {}; 
    } 
    if (!prev[curr.clientName][curr.day]) { 
     prev[curr.clientName][curr.day] = 0 
    } 
    prev[curr.clientName][curr.day] += curr.hoursWorked; 
    return prev; 
}, {}); 

你可以使用Array#forEach和检查存在的对象。如果不存在,则分配一个新的对象或值。

var timesheetItems = [{ clientName: 'client1', hoursWorked: 2, day: 'Monday' }, { clientName: 'client1', hoursWorked: 3, day: 'Monday' }, { clientName: 'client1', hoursWorked: 4, day: 'Wednesday' }, { clientName: 'client2', hoursWorked: 4, day: 'Monday' }], 
 
    grouped = {}; 
 

 
timesheetItems.forEach(a => { 
 
    grouped[a.clientName] = grouped[a.clientName] || {}; 
 
    grouped[a.clientName][a.day] = (grouped[a.clientName][a.day] || 0) + a.hoursWorked; 
 
}); 
 

 
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

我们可能利用tableMaker()函数从对象的数组,其中每个对象指定表格行生成一个表,所述对象的属性指定头和值是数据细胞。但首先我们必须将我们的数据转换成功能可以理解的形式。如

[ { 'Client Name': 'client1', 
    Monday: 5, 
    Tuesday: 0, 
    Wednesday: 4, 
    Thursday: 0, 
    Friday: 0 }, 
    { 'Client Name': 'client2', 
    Monday: 4, 
    Tuesday: 0, 
    Wednesday: 0, 
    Thursday: 0, 
    Friday: 0 } ] 

所以这里是表的代码。

function tableMaker(o,h=true){ 
 
    var keys = Object.keys(o[0]), 
 
    rowMaker = (a,t) => a.reduce((p,c,i,a) => p + (i === a.length-1 ? "<" + t + ">" + c + "</" + t + "></tr>" 
 
                    : "<" + t + ">" + c + "</" + t + ">"),"<tr>"), 
 
     rows = o.reduce((r,c) => r + rowMaker(keys.reduce((v,k) => v.concat(c[k]),[]),"td"),h ? rowMaker(keys,"th") : []); 
 
    return "<table>" + rows + "</table>"; 
 
} 
 

 
function giveMeNewClient(o){ 
 
    var templateObject = { 
 
    \t     "Client Name": "", 
 
    \t      "Monday": 0, 
 
    \t      "Tuesday": 0, 
 
    \t     "Wednesday": 0, 
 
    \t     "Thursday": 0, 
 
    \t      "Friday": 0 
 
         }; 
 
    return Object.assign(templateObject,o); 
 
} 
 
var timesheetItems = [{ 
 
         clientName: "client1", 
 
         hoursWorked: 2, 
 
           day: "Monday" 
 
         }, 
 
         { 
 
         \t clientName: "client1", 
 
         hoursWorked: 3, 
 
           day: "Monday" 
 
         }, 
 
         { 
 
         \t clientName: "client1", 
 
         hoursWorked: 4, 
 
           day: "Wednesday" 
 
         }, 
 
         { 
 
         \t clientName: "client2", 
 
         hoursWorked: 4, 
 
           day: "Monday" 
 
         } 
 
        ], 
 

 
     tableData = timesheetItems.reduce((res,c) => { var client = res.find(o => o["Client Name"] === c.clientName); 
 
                 client ? client[c.day]+= c.hoursWorked 
 
                   : res.push(giveMeNewClient({"Client Name": c.clientName, [c.day]: c.hoursWorked})); 
 
                 return res; 
 
                 },[]), 
 
     tableHTML = tableMaker(tableData); 
 
myTable.innerHTML = tableHTML;
<div id="myTable"></div>