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 = {
...
},
...
}
因此,如果任何人都可以提出如何去分组时间表项目数组,这样的结果会像上面的代码片段,这样我就可以轻松地从分组数组中循环来填充表格,这将非常有帮助。 谢谢。
答
要聚合的阵列可以使用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>
[阵列#减少(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) – Xotic750