3
votes

Comment calculer la moyenne en JavaScript des propriétés données dans le tableau d'objets

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/


1 commentaires

currentValue est l'objet, saisissez simplement la propriété qui vous intéresse -> currentValue.age


5 Réponses :


4
votes

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)


2 commentaires

"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



2
votes

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));


3 commentaires

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.



2
votes

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));


0 commentaires

4
votes

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.


0 commentaires

1
votes

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)));


0 commentaires