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)));
currentValueest l'objet, saisissez simplement la propriété qui vous intéresse ->currentValue.age