Используйте map()
и reduce()
из Array.prototype
.
const weeksByMonth = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].map(m => {
const byMonth = response.filter(x => x.month.substring(0, 3) == m);
if (byMonth.length)
return {
month: m,
weeks: [1, 2, 3, 4, 5].filter(w => byMonth.find(x => "Week" + w in x))
};
}).filter(m => m);
const monthWeeks = weeksByMonth.reduce((w, m) => w.concat(m.weeks.map(w => "Week" + w).concat("Total")), []);
const users = response.reduce((u, x) => {
if (!(x.UserName in u))
u[x.UserName] = {};
const user = u[x.UserName];
if (!(x.Type in user))
user[x.Type] = {};
const {UserName, Type, month, ...weeks} = x;
user[x.Type][x.month.substring(0, 3)] = weeks;
return u;
}, {});
$("#geo_summary thead").find("tr")
.append($("<td>"))
.append($("<td>"))
.append(weeksByMonth.map(m => $("<td>").text(m.month).attr("colspan", m.weeks.length + 1).css("text-align", "center")))
.after($("<tr>")
.append($("<td>").text(Object.keys(users)[0]))
.append($("<td>").text("Yearly"))
.append(monthWeeks.map(w => $("<td>").text(w))));
$("#geo_summary tbody").append(
Object.keys(users).reduce((r, u, i) => {
if(i)
r.push($("<tr>")
.append($("<td>").text(u))
.append(monthWeeks.map(w => $("<td>")))
);
const types = users[u];
return r.concat(Object.keys(types).sort().map(t => $("<tr>")
.append($("<td>").text(t))
.append($("<td>").text(Object.keys(types[t])
.reduce((y, m) => y + Object.keys(types[t][m] || {})
.reduce((y, w) => y + types[t][m][w], 0), 0)))
.append(weeksByMonth
.reduce((w, m) => {
const month = types[t][m.month] || {};
return w.concat(m.weeks.map(w => month["Week" + w] || 0)
.concat(Object.keys(month).reduce((t, w) => t + month[w], 0)));
}, [])
.map(t => $("<td>").text(t))
)
));
}, [])
);
https://codesandbox.io/s/elastic-diffie-ep56w