- Having to assign
sums
to a variable so that you canmap
over its keys is ugly. Yes, there's no better way to that with builtin JS methods, but this thing should be factored out into a helper function - Instead of using
forEach
, you can nestreduce
calls. Or just use a simplefor in
loop over each object's properties - it doesn't matter, you have to execute side effects anyway. - Instead of starting with an empty object, you could start with an object where all the known properties are initialised to nothing. That would avoid the
hasOwnProperty
check (which, as you have written it, is fragile is fragile anyway). - You have a bug for the case that
data.length
is0
-Object.keys
will fail. - Don't put the
console.log
insidesummary
, put it around the call and return youraverages
. Also I'm not sure wherethis.data
comes from, better take it as a parameter.
- Having to assign
sums
to a variable so that you canmap
over its keys is ugly. Yes, there's no better way to that with builtin JS methods, but this thing should be factored out into a helper function - Instead of using
forEach
, you can nestreduce
calls. Or just use a simplefor in
loop over each object's properties - it doesn't matter, you have to execute side effects anyway. - Instead of starting with an empty object, you could start with an object where all the known properties are initialised to nothing. That would avoid the
hasOwnProperty
check (which, as you have written it, is fragile anyway). - You have a bug for the case that
data.length
is0
-Object.keys
will fail. - Don't put the
console.log
insidesummary
, put it around the call and return youraverages
. Also I'm not sure wherethis.data
comes from, better take it as a parameter.
- Having to assign
sums
to a variable so that you canmap
over its keys is ugly. Yes, there's no better way to that with builtin JS methods, but this thing should be factored out into a helper function - Instead of using
forEach
, you can nestreduce
calls. Or just use a simplefor in
loop over each object's properties - it doesn't matter, you have to execute side effects anyway. - Instead of starting with an empty object, you could start with an object where all the known properties are initialised to nothing. That would avoid the
hasOwnProperty
check (which, as you have written it, is fragile anyway). - You have a bug for the case that
data.length
is0
-Object.keys
will fail. - Don't put the
console.log
insidesummary
, put it around the call and return youraverages
. Also I'm not sure wherethis.data
comes from, better take it as a parameter.
Your approach is mostly OK, but I can see some points that could be improved:
- Having to assign
sums
to a variable so that you canmap
over its keys is ugly. Yes, there's no better way to that with builtin JS methods, but this thing should be factored out into a helper function - Instead of using
forEach
, you can nestreduce
calls. Or just use a simplefor in
loop over each object's properties - it doesn't matter, you have to execute side effects anyway. - Instead of starting with an empty object, you could start with an object where all the known properties are initialised to nothing. That would avoid the
hasOwnProperty
check (which, as you have written it, is fragile anyway). - You have a bug for the case that
data.length
is0
-Object.keys
will fail. - Don't put the
console.log
insidesummary
, put it around the call and return youraverages
. Also I'm not sure wherethis.data
comes from, better take it as a parameter.
function mapObject(o, fn) {
return Object.keys(o).map(k => fn(o[k], k));
}
function summary(data) {
if (!data.length) return {};
var keys = Object.keys(data[0]);
return mapObject(data.reduce((previous, element) => {
return keys.reduce((previous, k) => {
if (element[k] != null) {
previous[k].value += element[k];
previous[k].count += 1;
}
return previous;
}, previous);
}, keys.reduce(function(sums, k) {
sums[k] = {value: 0, count: 0};
return sums;
}, {})), (x, name) => ({
name,
average: x.value / x.count
}));
}
or
function summary(data) {
return mapObject(data.reduce((previous, element) => {
for (k in element) {
if (element[k] == null) continue;
if (k in previous) {
previous[k].value += element[k];
previous[k].count += 1;
} else {
previous[k] = { value: element[k], count: 1 };
}
}
return previous;
}, {}), (x, name) => ({
name,
average: x.value / x.count
}));
}
lang-js