Voici quelques données:
var avg = {};
var rows = data.length;
data.forEach(obj => {
Object.keys(obj).forEach(k => {
if(obj[k] != null){
avg[k] = (avg[k] || 0) + obj[k] / rows;
}
});
});
return avg;
à partir desquelles j'essaie de calculer la moyenne de leurs propriétés:
data = [
{"Age":26,"Level":8},
{"Age":37,"Level":9},
{"Age":null,"Level":15},
{"Age":null,"Level":45}
];
mais le problème est dans les éléments qui ont des propriétés avec des valeurs null , où j'essaie d'exclure les valeurs null du calcul, et si vous jetez un oeil à la codepen il y a Âge: 15,75 au lieu de 31,5
car la longueur des données est toujours de 4 (et devrait être de 2 puisque 2 d'entre elles sont nulles ). Quelle serait la meilleure façon d'obtenir la longueur pour ne pas inclure les nulls?
6 Réponses :
Vous pouvez utiliser un simple pour ... sur et for ... in boucle pour obtenir la somme et count pour chaque non- élément nul. Vous pouvez ajouter un get propriété pour calculer automatiquement la moyenne en fonction des propriétés sum et count dans les données du compteur
const data = [{Age:26,Level:8},{Age:37,Level:9},{Age:null,Level:15},{Age:null,Level:45}];
let counter = {}
for (const item of data) {
for (const key in item) {
if (item[key] !== null) {
counter[key] = counter[key] || {
sum: 0,
count: 0,
get average() { return this.sum/this.count }
};
counter[key].sum += item[key]
counter[key].count++
}
}
}
console.log(counter)
Vous pouvez stocker la somme et le nombre de chaque clé indépendamment.
.as-console-wrapper { max-height: 100% !important; top: 0; }
var data = [{ "Age": 26, "Level": 8 }, { "Age": 37, "Level": 9 }, { "Age": null, "Level": 15 }, { "Age": null, "Level": 45 }],
avg = {},
temp = {};
data.forEach(obj => Object.keys(obj).forEach(k => {
if (obj[k] === null) return;
temp[k] = temp[k] || { sum: 0, count: 0 };
temp[k].sum += obj[k];
temp[k].count++;
avg[k] = temp[k].sum / temp[k].count;
}));
console.log(avg);
console.log(temp);
Je n'aime pas comment cela recalcule la moyenne à chaque fois qu'il incrémente le compte. C'est pourquoi je dois acheter un ordinateur portable plus rapide tous les quelques années.
@Wyck, vous pouvez déplacer le calcul en dehors de la boucle. pas besoin d'acheter un nouvel ordinateur portable.
Vous pouvez avoir un objet avec un objet imbriqué qui a deux propriétés value et count
const data = [
{"Age":26,"Level":8},
{"Age":37,"Level":9},
{"Age":null,"Level":15},
{"Age":null,"Level":45}
];
let avg = {}
data.forEach(x => {
for(let k in x){
if(!avg[k]){
avg[k] = {value:0,count:0};
}
if(x[k] !== null){
avg[k].value += x[k]
avg[k].count++;
}
}
})
avg = Object.fromEntries(Object.entries(avg).map(([k,v]) => ([k,v.value/v.count])))
console.log(avg)
let data = [
{"Age": 26, "Level": 8},
{"Age": 37, "Level": 9},
{"Age": null, "Level": 15},
{"Age": null, "Level": 45}
];
let averages = data.reduce((values, o) => {
Object.entries(o).forEach(([k, v]) => {
if (v !== null)
values[k] = (values[k] || []).concat(v);
});
return values;
}, {});
Object.entries(averages).forEach(([k, vs]) =>
averages[k] = vs.reduce((a, b) => a + b) / vs.length);
console.log(averages);
Je ferais quelque chose comme ceci: (pas encore testé)
var data = [
{"Age":26,"Level":8},
{"Age":37,"Level":9},
{"Age":null,"Level":15},
{"Age":null,"Level":45}
];
var sum = { "Age": 0, "Level": 0 };
var average = { "Age": 0, "Level": 0 };
var sumCount = { "Age": 0, "Level": 0 };
// sum up all objects
for (var i = 0; i < data.length; i++) {
Object.keys(data[i]).forEach(function (key) {
if (data[i][key] == null || data[i][key] == undefined)
return;
sumCount[key]++;
sum[key] = sum[key] + data[i][key];
});
}
// make average object
Object.keys(average).forEach(function (key) {
average[key] = sum[key] / sumCount[key];
});
Vous pouvez également le faire de manière relativement concise avec seulement Array.reduce et à l'intérieur, il suffit de parcourir le Object.keys :
var data = [ {"Age":26,"Level":8}, {"Age":37,"Level":9}, {"Age":null,"Level":15}, {"Age":null,"Level":45} ];
let result = data.reduce((r, c) => (Object.keys(c).forEach(k => {
r[k] = (r[k] || { Sum: 0, Count: 0, Avg: 0 })
r[k].Sum += c[k] || 0
r[k].Count += c[k] ? 1 : 0
r[k].Avg = r[k].Sum / r[k].Count
}), r), {})
console.log(result)
Et si tous les âges sont nuls? Que voulez-vous qu'il se passe alors?
Ecrire probablement null