J'ai un tableau d'objets. Chaque objet contient quelques propriétés et l'une de ces propriétés est l'âge.
let getAverage = arr => { let reducer = (total, currentValue) => total + currentValue; let sum = arr.reduce(reducer) return sum / arr.length; }
Je veux calculer la moyenne de toutes les propriétés d'âge de ce tableau. J'utilise cette fonction:
var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ]
Cela fonctionne bien pour le tableau simple comme [22, 34, 12] mais ce n'est pas le cas pour les tableaux d'objets.
Comment modifier ma fonction getAverage pour qu'elle fonctionne également avec des tableaux d'objets?
Voici l'extrait de code avec mon code: https://jsfiddle.net/marektchas/kc8Ls0f5/2/
5 Réponses :
Vous pouvez utiliser reduction ()
et ajouter la propriété age
de chaque objet du tableau à ac
. N'oubliez pas de passer 0
(valeur initiale de ac
) comme deuxième argument sinon il renverrait NaN
var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ] let avgs = people.reduce((ac,a) => a.age + ac,0)/people.length console.log(avgs)
"Vous pouvez utiliser reduction ()
..." (ce que TO fait déjà) "... et ajouter la propriété age
... " (la vraie solution) " ..to ac
" (qu'est-ce que ac
?). Et que diriez-vous d'expliquer la partie ac, 0
?
@Andreas Que diriez-vous ac
, accumulateur. J'ai modifié le message si vous avez d'autres suggestions, veuillez donc donner
Nous pouvons utiliser Array.reduce
pour calculer la somme, où acc
est la somme accumulée et les objets individuels sont déstructurés à l ' âge
variable puis calculez la moyenne en divisant la somme par la longueur du tableau:
var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ]; function getAvg(arr){ return (new Function(`return ${people.map(({age}) => age).join("+")}`)()) / arr.length; } console.log(getAvg(people));
Nous pouvons également mapper la fonction à la propriété age
et calculer la somme en joignant le tableau dans une chaîne et en l'évaluant dans le constructeur Function
:
var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ]; function getAvg(arr){ return (people.reduce((acc, {age}) => (acc + age), 0))/arr.length; } console.log(getAvg(people));
Il est préférable de faire une seule division après le calcul de la somme que de diviser à chaque fois. Cela minimisera les erreurs d'arrondi et sera également plus efficace
La carte
et le calcul de la moyenne à chaque itération sont inutiles
Merci les gars! J'ai fait les correctifs.
Vous pouvez fournir une fonction pour la propriété souhaitée et réduire avec une valeur de départ.
const getAverage = (array, fn = v => v) => { var reducer = fn => (total, item) => total + fn(item), sum = array.reduce(reducer(fn), 0); return sum / array.length; }; var people = [{ name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }]; console.log(getAverage(people, o => o.age));
Vous n'avez pas besoin de modifier getAverage
- vous pouvez prétraiter le tableau avant de le remettre, auquel cas getAverage
fonctionnera exactement comme nécessaire:
var numbers = [ 1, 2, 3, 4, 5 ] var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ] var moreComplexObjects = [ { a: { b: { c: 6 } } }, { a: { b: { c: 7 } } }, { a: { b: { c: 8 } } } ] //the default value of the second parameter is a function that returns the input let getAverage = (arr, valueExtractor = x => x) => { //extract the value of each element let reducer = (total, currentValue) => total + valueExtractor(currentValue); let sum = arr.reduce(reducer, 0) //make sure you add an initialiser return sum / arr.length; } const ageExtractor = person => person.age; const complexKeyExtractor = obj => obj.a.b.c; console.log(getAverage(numbers)); console.log(getAverage(people, ageExtractor)); console.log(getAverage(moreComplexObjects, complexKeyExtractor));
Si vous souhaitez modifier getAverage
, afin qu'il puisse gérer n'importe quel type d'entrée potentiel, vous pouvez ajouter un argument facultatif qui effectuera une extraction de valeur, donc vous n'avez pas pour exécuter une carte
sur chaque tableau.
var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ] let getAverage = arr => { let reducer = (total, currentValue) => total + currentValue; let sum = arr.reduce(reducer) return sum / arr.length; } let ages = people.map(person => person.age); console.log(getAverage(ages));
Une note pour ce qui précède, si vous ne fournissez pas de deuxième paramètre à Array # reduction
, puis la première exécution total
être le premier élément du tableau, cependant la deuxième fois et après, ce sera la somme jusqu'à présent. Cela ne vaut pas la peine de traiter ce cas, donc fournir une valeur initiale le résout.
Code plus simplifié
exécutez simplement en tant que getAverage (people.map (p => p.age)); en utilisant votre code
var people = [ { name: 'Anna', age: 22 }, { name: 'Tom', age: 34 }, { name: 'John', age: 12 }, ]; let getAverage = arr => { let reducer = (total, currentValue) => total + currentValue; let sum = arr.reduce(reducer) return sum / arr.length; }; console.log(getAverage(people.map(p=> p.age)));
currentValue
est l'objet, saisissez simplement la propriété qui vous intéresse ->currentValue.age