Search code examples
javascriptarraysmultidimensional-arrayaverageparseint

how can i compute this average with multidimensional array?


I need to compute this kind of average:

stars = [["3", "ciccio"];["5", "ciccio"];["1", "ciccio"];["1", "ciccio"];["5", "ciccio"];["2", "caramella"]]

what i want is:

avrgArr = [[3, ciccio];[2, caramella]]

my code is:

var moon = stars.length-1;

for (var y = 0; y < stars.length; y++) {
    avrg= parseInt(stars[y][0]);
    for (var z = 1; z < moon; z++) {
      if (stars[y][1] === stars[z][1]) {  
        avrg+= parseInt(stars[z][0]); 
        count++;
      }
    }
    avrg= avrg/ count;
    avrgArr.push([avrg, stars[y][1]]);
  }

But this code gives me the average of every element, like:

avrgArr = [[3.75, ciccio];[2.125, ciccio];[1.0833333333, ciccio];[0.8125, ciccio];[0.85, ciccio];[0.1 caramella]]

How can i solve this? Thank you :)


Solution

  • First, use an O(n) pass through the data to generate an object that has the name as the keys and the sum and count of each name as the values:

    const stars = [["3", "ciccio"],["5", "ciccio"],["1", "ciccio"],["1", "ciccio"],["5", "ciccio"],["2", "caramella"]];
    
    // helper function for reduce
    const sum = (data, [value, name]) => {
      value = parseInt(value, 10);
    
      // create empty entry if none found
      data[name] = data[name] || { count: 0, sum: 0 };  
    
      // accumulate data
      data[name].count += 1;
      data[name].sum += value;
    
      return data;
    }
    
    const aggregates = stars.reduce(sum, {});
    

    At this point you'll have:

    { ciccio: { count: 5, sum: 15 }, caramella: { count: 1, sum: 2 } }
    

    This object is quite usable as is, but if you absolutely require the array structure defined in your question you can convert this object into that structure with another O(m) pass over the intermediate result:

    const result = Object.entries(aggregates).map(([name, {count, sum}]) => {
      return [ sum / count, name ];
    });