2010-12-07 23 views
3

J'ai deux tableaux de hachages. Les clés des hash sont différentes:Comment ajouter des valeurs à partir de deux tableaux de hachages différents?

player_scores1 = [{:first_name=>"Bruce", :score => 43, :time => 50}, 
        {:first_name=>"Clark", :score => 45, :minutes => 20}] 

player_scores2 = [{:last_name=>"Wayne", :points => 13, :time => 40}, 
        {:last_name=>"Kent", :points => 3, :minutes => 20}] 

J'aimerais créer un nouveau tableau de hachages qui ajoute: score et: points ensemble et l'associer à une clé appelée: score. J'aimerais aussi combiner: first_name et: last_name et l'assigner à une clé appelée: full_name. Je veux jeter toutes les autres clés.

Cela se traduirait par ce tableau:

all_players = [{:full_name => "Bruce Wayne", :score => 56}, 
       {:full_name => "Clark Kent", :score => 48}] 

Y at-il une façon élégante de le faire?

Répondre

8

Quelque chose comme ceci:

player_scores1.zip(player_scores2).map { |a,b| 
    { 
     :full_name => a[:first_name]+' '+b[:last_name], 
     :score => a[:score]+b[:points] 
    } 
} 
+0

Cool, n'avait pas entendu parler de la méthode zip avant! – Chanpory

+0

Cette fonction http://en.wikipedia.org/wiki/Convolution_(computer_science) existe dans beaucoup de langues: Python, Haskell ... – Nakilon

+2

+1, mais je pense que c'est idiomatique Ruby d'utiliser do-end sur multi- blocs de ligne. – tokland

0

Le code que vous recherchez est:

final = [] 
player_scores1.each_index do |index| 
    entry_1 = player_scores1.values(index) 
    entry_2 = player_scores2.values(index)[:first_name] 
    score = entry_1[:score] + entry_2[:points] 
    final << {:full_name => "#{entry_1[:first_name]} #{entry_2[:last_name]}", :score => score } 
end 

Toutes les suggestions sur ce resserrement en serait très apprécié!

+0

Est-ce que ce travail, si les clés sont différentes? – Chanpory

+0

Juste essayé ceci, et a eu une erreur: '" NoMethodError: méthode undefined 'fusionnez' pour # \t de (irb): 15 "' – Chanpory

+0

juste relu la question - ma réponse est fausse, laissez-moi refaire les choses. –

0

Cela fonctionne. Je ne sais pas si c'est assez élégant cependant.

player_scores1 = [{:first_name=>"Bruce", :score => 43, :time => 50}, 
        {:first_name=>"Clark", :score => 45, :minutes => 20}] 

player_scores2 = [{:last_name=>"Wayne", :points => 13, :time => 40}, 
        {:last_name=>"Kent", :points => 3, :minutes => 20}] 

p (0...[player_scores1.length, player_scores2.length].min).map {|i| { 
    :full_name => player_scores1[i][:first_name] + " " + player_scores2[i][:last_name], 
    :score => player_scores1[i][:score] + player_scores2[i][:points] 
}} 

Cet exemple sur Codepad.

0

Il utilise zip avec un bloc en boucle sur les hash, joignant les noms et résumant:

all_players = [] 
player_scores1.zip(player_scores2) { |a, b| 
    all_players << { 
    :full_name => a[:first_name] + ' ' + b[:last_name], 
    :score  => a[:score] + b[:points] 
    } 
} 
all_players # => [{:full_name=>"Bruce Wayne", :score=>56}, {:full_name=>"Clark Kent", :score=>48}] 
+1

init un tableau vide + ajoute des valeurs dans une boucle + retourne le tableau = map – tokland

+0

Habituellement. Cela supprime l'étape supplémentaire habituelle que les gens feraient de 'zip.each' en laissant le bloc pour zip le faire.Il ne sert à rien de faire une nouvelle itération sur les hachages puisque zip fait déjà une boucle sur chacun d'eux. –