8
votes

Comment calculer les valeurs moyennes des objets situés dans un tableau?

Disons que j'ai un tableau comme celui-ci:

[
  {
    "player_id"         => 1,
    "number_of_matches" => 2,
    "goals"             => 5
  },
  {
    "player_id"         => 2,
    "number_of_matches" => 4,
    "goals"             => 10
  }
]


5 commentaires

Vous voudrez peut-être réparer votre tableau / hachage afin qu'il soit réellement valide ruby.


Désolé, je reçois un Json et je le mappe à un hachage. Laissez-moi éditer ça.


Des doublures sont intéressantes, mais souvent surestimées, imo. Je pense que demander une solution Elegant et Clean est meilleur que de demander un one-liner.


@Andrew: D'accord, surtout parce que cela ne semble pas être un problème qui peut être résolu élégamment dans une libe.


@Andrewmarshall vous avez raison. Je vais prendre en compte cela lors de la formulation de ce type de questions pour éviter toute confusion dans les réponses.


4 Réponses :


17
votes

Comme demandé, une doublure one-liner: xxx

un extrait plus lisible: xxx


6 commentaires

Kyle: Faire cela dans une ligne nécessitera une répétition de code ou des résultats inexacts.


Niklas: répétition de code? S'il vous plaît expliquer comment ma solution est en train de répéter le code? Cela fait une passe sur le tableau et produit le résultat.


@Kyle: J'ai dit ou des résultats inexacts , comme votre solution, qui résume les erreurs de division individuelles. Si du tout, vous devez utiliser rationnel .


Une solution à une doublure entraînera un résultat inexact sur de gros nombres, s'il vous plaît regarder ma variante


@Kyle: Il suffit de remplacer chaque rupture de ligne avec un point-virgule. Voimà: une doublure.


@ Jörgwmittag J'ai répondu avec ma solution de doublure.



0
votes
a = [{player_id:1 , match_num:2, goals: 5}, {player_id:2 , match_num:4, goals: 10}]

a.reduce(0){|avg, p| avg += p[:goals].to_f/p[:match_num]}/a.size
Edit: renamed keys and block args to reduce char count. For those who care.First, your keys need to use => if your going to use strings as keys. reduce will iterate over the array and sum the individual averages for each player and finally we divide that result by the number of total players. The '0' in the parenthesis is your starting number for reduce.

4 commentaires

arr.map {| p | P [: objectifs] .to_f / p [: number_of_matches]} .ReRuce (: +) / arr.size serait un peu plus court (et ne débordez pas le code DIV).


Sur 93 caractères de votre one-liner, seuls 3 sont des espaces et quelques autres opérateurs le rendraient beaucoup plus lisibles.


Niklas: Vous êtes en mappage, puis réduisez, ainsi itérant sur la matrice deux fois lorsqu'un seul passage est requis.


@KYLE: Oui, mais une doublure unique qui ne correspond pas à l'écran n'est pas une doublure. Le code devrait généralement envelopper à environ la colonne 80. Si la performance était une préoccupation, on ne choisirait probablement pas de rubis pour le travail. De plus, les deux solutions sont O (n) , donc ce n'est pas une différence algorithmique "réelle".



1
votes

Une légère modification de la réponse de Tokland.

items.map{|e| e.values_at("goals", "number_of_matches")}.transpose.map{|e| e.inject(:+)}.instance_eval{|goals, matches| goals.to_f/matches}


1 commentaires

Heh, belle astuce avec instance_eval :) Je préférerais ne pas voir cela dans le code de production, cependant: p



0
votes

Pour faire de la chaîne plus courte, permet de renommer "number_of_matches" à "correspond" xxx


0 commentaires