sf2k
sf2k

Reputation: 592

How to build hash from array

This is a rock paper scissors game. From irb, game.class says it's an array. I hope to find the name of the person who won the game (in this case Player2).

game = [["Player1", "P"], ["Player2", "S"]]

The approach that comes to mind is to return a Hash with the name values split up. Then search that hash via the value to get the player name.

h = Hash.new(0)
game.collect do |f|
  h[f] = f[1]
end
h
#=> {["Player1", "P"]=>"P", ["Player2", "S"]=>"S"}

This is close but no cigar. I want

{"Player1" => "P", "Player2" => "S"}

I tried again with inject method:

game.flatten.inject({}) do |player, tactic| 
  player[tactic] = tactic  
  player 
end
#=> {"Player1"=>"Player1", "P"=>"P", "Player2"=>"Player2", "S"=>"S"}

This did not work:

Hash[game.map {|i| [i(0), i(1)] }]
#=> NoMethodError: undefined method `i' for main:Object

I would appreciate some pointers to something that will help me understand.

Upvotes: 2

Views: 334

Answers (4)

lalit.sethi143
lalit.sethi143

Reputation: 146

You can use Ruby's built in Array#to_h method for this:

game.to_h
#=> {"Player1"=>"P", "Player2"=>"S"}

Upvotes: 0

Andrew Grimm
Andrew Grimm

Reputation: 81470

Using each_with_object means you don't need to have two statements in the block, like in xdazz's answer

game.each_with_object({}){ |h, k| h[k[0]] = k[1] }

You can make this even more readable by destructuring the second block parameter

game.each_with_object({}){ |hash, (name, tactic)| hash[name] = tactic }

Upvotes: 2

oldergod
oldergod

Reputation: 15010

You can simply do this too.

game = [["Player1", "P"], ["Player2", "S"]]
#=> [["Player1", "P"], ["Player2", "S"]]
Hash[game]
#=> {"Player1"=>"P", "Player2"=>"S"}

Upvotes: 3

xdazz
xdazz

Reputation: 160833

Use:

game.inject({}){ |h, k| h[k[0]] = k[1]; h }

Upvotes: 2

Related Questions