Как рассчитать средний рейтинг массива?

#javascript #arrays #average

#javascript #массивы #среднее

Вопрос:

Ниже приведены данные массива:

     const ratingData = [
        {name: 'St. Marys School', rating:5},
        {name: 'St. Zaviers School', rating:4},
        {name: 'St. Marys School', rating:3},
        {name: 'Rahul English Medium School', rating:2},
        {name: 'St. Francis High School', rating:3},
        {name: 'Rahul English Medium School', rating:1},
        {name: 'St. Francis High School', rating:4},
        {name: 'Mother Marys High School', rating:5}
    ];

  

В этом массиве я хочу рассчитать среднюю оценку данных каждой школы. Но проблема заключается в повторяющихся записях, например, для «St. Школа Мэри» с разными оценками. Как я могу объединить в один и рассчитать его средний рейтинг? Я пытался использовать map функцию, но для каждой записи, но она не работает.

Это o / p должно выглядеть примерно так. (Это просто пример)

 const output = [
     { name: 'St. Marys School', averageRating: 4},
     { name: 'St. Zaviers School', averageRating: 4},
     { name: 'Rahul English Medium School', averageRating: 1.5},
     { name: 'St. Francis High School', averageRating: 3.5},
     { name: 'Mother Marys High School', averageRating: 5}
];
  

Комментарии:

1. array.reduce() твой друг здесь.

2. Я бы сделал это в несколько этапов — сначала построил карту name => ratings , затем усреднил рейтинги, а затем переструктурировал ее в желаемый выходной массив.

Ответ №1:

 let ratingData = [
    {name: 'St. Marys School', rating:5},
    {name: 'St. Zaviers School', rating:4},
    {name: 'St. Marys School', rating:3},
    {name: 'Rahul English Medium School', rating:2},
    {name: 'St. Francis High School', rating:3},
    {name: 'Rahul English Medium School', rating:1},
    {name: 'St. Francis High School', rating:4},
    {name: 'Mother Marys High School', rating:5}
];

let sumData = {};

for (let element of ratingData) {
    if (sumData[element.name]) {
        sumData[element.name].sum = sumData[element.name].sum   element.rating;
        sumData[element.name].n  ;
    } else {
        sumData[element.name] = {
            sum: element.rating,
            n: 1
        };
    }
}

console.log('sumData: '   JSON.stringify(sumData));

let averageData = [];

for (let element of Object.keys(sumData)) {
    averageData.push({
        name: element,
        rating: sumData[element].sum / sumData[element].n
    });
}

console.log('averageData: '   JSON.stringify(averageData));
  

sumData будет равно

 {
    "St. Marys School": {
        "sum": 8,
        "n": 2
    },
    "St. Zaviers School": {
        "sum": 4,
        "n": 1
    },
    "Rahul English Medium School": {
        "sum": 3,
        "n": 2
    },
    "St. Francis High School": {
        "sum": 7,
        "n": 2
    },
    "Mother Marys High School": {
        "sum": 5,
        "n": 1
    }
}
  

и средние данные будут равны

 [
    {
        "name": "St. Marys School",
        "rating": 4
    },
    {
        "name": "St. Zaviers School",
        "rating": 4
    },
    {
        "name": "Rahul English Medium School",
        "rating": 1.5
    },
    {
        "name": "St. Francis High School",
        "rating": 3.5
    },
    {
        "name": "Mother Marys High School",
        "rating": 5
    }
]
  

Ответ №2:

Вот пример использования reduce() в сочетании с a Map для обнаружения повторяющихся записей.

Сначала он уменьшает исходный массив до a Map , который накапливает рейтинги повторяющихся записей в массиве.

 {
{'St. Marys School': [5, 3, 1]},
{'St. Zaviers School': [4]},
...
}
  

Затем мы преобразуем это Map обратно в массив, используя Array.from и уменьшая массив оценок до среднего.

 const ratingData = [
    {name: 'St. Marys School', rating:5},
    {name: 'St. Zaviers School', rating:4},
    {name: 'St. Marys School', rating:3},
    {name: 'Rahul English Medium School', rating:2},
    {name: 'St. Francis High School', rating:3},
    {name: 'Rahul English Medium School', rating:1},
    {name: 'St. Francis High School', rating:4},
    {name: 'Mother Marys High School', rating:5},
    {name: 'St. Marys School', rating:1}
    ]
    
const mapData = ratingData.reduce((acc, {name, rating}) => {
  const match = acc.get(name);
  match ? 
  match.push(rating) :
  acc.set(name, [rating]);
  return acc;
}, new Map);

const averageArray = Array.from(mapData, ([name, ratings]) => {
  const rating = ratings.reduce((a, r) => (a   r))/ratings.length;
  return { name, rating }
});

console.log(averageArray);  

Комментарии:

1. Ваше «усреднение» ошибочно. 5, 3, 1 должно быть в среднем 3 , но ваш код усредняет его 2.5 , поскольку он сначала усредняет 5,3 => 4 , а затем 4,1 => 2.5