0

So I have this array of objects

audioFeatures = [
    {danceability: 10, loudness: 2, instrumentalness: 4, energy: 5, acousticness: 7},
    {danceability: 6, loudness: 3, instrumentalness: 8, energy: 9, acousticness: 5},
    {danceability: 7, loudness: 5, instrumentalness: 6, energy: 2, acousticness: 5},
    {danceability: 8, loudness: 10, instrumentalness: 9, energy: 7, acousticness: 2},
]

And I want to calculate a mean value for each property i.e. danceability should = (10+6+7+8)/4 and so on. I have got this working through a plethora of for loops but it seems really inefficient and I ideally want to end up with one object containing each mean value which I haven't figured out.

Does anyone know of a nice way of doing this. I'm coding this in JavaScript but any advise would be appreciated and I can try implement it. I have been trying map but can't quite get my head around how to apply it to this (maybe nested map lol, that's probably not a good idea)

Salty511
  • 11
  • 3

3 Answers3

8

You just need two for loops:

audioFeatures = [
    {danceability: 10, loudness: 2, instrumentalness: 4, energy: 5, acousticness: 7},
    {danceability: 6, loudness: 3, instrumentalness: 8, energy: 9, acousticness: 5},
    {danceability: 7, loudness: 5, instrumentalness: 6, energy: 2, acousticness: 5},
    {danceability: 8, loudness: 10, instrumentalness: 9, energy: 7, acousticness: 2},
]

const average = {};

for (const feature of audioFeatures) {
  for (const [key, value] of Object.entries(feature)) {
    if (!average[key]) average[key] = 0;
    average[key] += value / audioFeatures.length;
  }
}

console.log(average);
Herohtar
  • 5,347
  • 4
  • 31
  • 41
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
1

You could add the nth part of the value for the averages by iterating the array and the key/value pairs of the objects.

var audioFeatures = [{ danceability: 10, loudness: 2, instrumentalness: 4, energy: 5, acousticness: 7 }, { danceability: 6, loudness: 3, instrumentalness: 8, energy: 9, acousticness: 5 }, { danceability: 7, loudness: 5, instrumentalness: 6, energy: 2, acousticness: 5 }, { danceability: 8, loudness: 10, instrumentalness: 9, energy: 7, acousticness: 2 }],
    averages = audioFeatures.reduce((result, object, _, { length }) => {
        Object
            .entries(object)
            .forEach(([key, value]) => result[key] = (result[key] || 0) + value / length);
        return result;
    }, Object.create(null));
    
console.log(averages);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 3
    Probably because this code is unreadable trying to be "cute". – Trasiva Nov 08 '18 at 19:54
  • 3
    @Trasiva, this has nothing to do with "cute", but all with functional programming style. – trincot Nov 08 '18 at 19:55
  • 1
    Destructuring the length directly from the array parameter of reduce and short-circuiting the key to 0 if it doesn't exist are good tricks! Nice job! – zfrisch Nov 08 '18 at 19:55
  • 2
    I'm still curious to see a real-world codebase written in that style :) – Jonas Wilms Nov 08 '18 at 19:56
  • @trincot Go ahead, use code like that in a real work environment. See what your coworkers think of it. That code is *not* easily readable and self-commenting. – Trasiva Nov 08 '18 at 19:57
  • @Trasiva It wasn't unreadable. Though I understand there could be some frustration if you were being introduced to reduce through this answer, but really I think syntax is reasonable to assume that someone could look up. Pulling apart, playing, and researching code is how you learn the nuances. – zfrisch Nov 08 '18 at 19:59
  • @JonasWilms, look at Haskell, Clojure, ... (e.g. https://wiki.haskell.org/Haskell_in_industry) – trincot Nov 08 '18 at 20:15
0

Try out this one:

var audioFeatures = [
 {danceability: 10, loudness: 2, instrumentalness: 4, energy: 5, acousticness: 7},
 {danceability: 6, loudness: 3, instrumentalness: 8, energy: 9, acousticness: 5},
 {danceability: 7, loudness: 5, instrumentalness: 6, energy: 2, acousticness: 5},
 {danceability: 8, loudness: 10, instrumentalness: 9, energy: 7, acousticness: 2},
];
var meanValues = [];
Object.keys(audioFeatures[0]).forEach(key => {
 console.log(key,
  meanValues[key] = (audioFeatures
   .map(a => a[key])
   .reduce((a, b) => a + b)
   / audioFeatures.length));
});
  1. Find all keys.
  2. For each key create a map (it will return an array of all values of this key)
  3. Get sum off array using .reduce method.
  4. divide by array length and write it to the variable.