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 null
s?
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