This is my code
lunch_order = {
"Ryan" => "wonton soup",
"Eric" => "hamburger",
"Jimmy" => "sandwich",
"Sasha" => "salad",
"Cole" => "taco"
}
lunch_order.each { |element| puts element }
I want the value to be printed out, but here, both the value and the key are printed.
You can use
lunch_order.each { |key, value| puts value}
Codepad Example
You can loop over the values only with each_value
h = { "a" => 100, "b" => 200 }
h.each_value {|value| puts value }
You can read more about api of hash here.
So many ways to do it in Ruby:
lunch_order.values.each { |element| puts element }
In Ruby a hash contains Keys and Values. So in your case the keys are:
Keys
Ryan
Eric
Jimmy
Sasha
Cole
And the Values for those keys are:
Values
Wonton Soup
Hamburger
Sandwich
Salad
Taco
And all you'd need to do to call the values is use the each loops like you've done but instead of using element as the local variable within the block, you use something like this:
lunch_order.each do { |key, value| puts value }
lunch_order.each_pair { |key,value| puts value }
Docs: http://apidock.com/ruby/Hash/each_pair
Given your original code
lunch_order = {
"Ryan" => "wonton soup",
"Eric" => "hamburger",
"Jimmy" => "sandwich",
"Sasha" => "salad",
"Cole" => "taco"
}
You created a hash, which consists of both keys and values. Keys are on the left, values on the right. To get only the values use
lunch_order.values.each{|value| puts value}
Hope this helps.
Related
I have a Hash that looks like this:
{
:a => "700",
:b => "600",
:c => "500",
:d => "400",
:e => "300",
:f => {
:g => "200",
:h => [
"test"
]
}
}
my goal is to iterate over this hash and return a copy that have all the values wrapped in a lambda, similar to this: https://github.com/thoughtbot/paperclip/blob/dca87ec5d8038b2d436a75ad6119c8eb67b73e70/spec/paperclip/style_spec.rb#L44
I went with each_with_object({}) but best I can do is to wrap only the first level, so I tried to check when I meet another Hash in the cycle (:f in this case, only it's key's values should be a lambda unless they are a hash as well) and treat it, but it's becoming quite troublesome.
def hash_values_to_lambda(old_hash)
{}.tap do |new_hash|
old_hash.each do |key, value|
new_hash[key] =
if value.is_a?(Hash)
hash_values_to_lambda(value)
else
lambda { value } # or -> { value } with new syntax
end
end
end
end
If you want, you can go with each_with_object instead of tap:
old_hash.each_with_object({}) do |(key, value), new_hash|
# everything else remains the same
end
I am a beginner and am looking for a method to iterate through a hash containing hashed values. E.g. I only want to print a list of all values of inner hash-elements of the key named "label". My array is looking like this:
ary = Hash.new
ary[:item_1] = Hash[ :label => "label_1" ]
ary[:item_2] = Hash[ :label => "label_2" ]
ary[:item_3] = Hash[ :label => "label_3" ]
Now I want to iterate through all elements of the outer hash and try this:
ary.keys.each { |item| puts ary[:item] }
or this:
ary.keys.each { |item[:label]| puts ary[:item] }
Unfortunately both do not work. But if I try this - quite crazy feeling - detour, I get the result, which is I want to:
ary.keys.each { |item|
evalstr = "ary[:" + item.to_s + "][:label]"
puts eval(evalstr)
}
This yields the result:
label_1
label_2
label_3
I am absolutely sure that there must exist be a better method, but I have no idea how to find this method.
Thanks very much for your hints!
You can iterate through all values of an hash using each_value; or, you can iterate trough all key/value pairs of an hash using each, which will yield two variables, key and value.
If you want to print a single value for each hash value of the outer hash, you should go for something like this:
ary.each_value { |x| puts x[:label] }
Here's a more complex example that shows how each works:
ary.each { |key, value| puts "the value for :label for #{key} is #{value[:label]}" }
ary = Hash.new
ary[:item_1] = Hash[ :label => "label_1" ]
ary[:item_2] = Hash[ :label => "label_2" ]
ary[:item_3] = Hash[ :label => "label_3" ]
ary.flat_map{|_,v| v.values}
#=>["label_1", "label_2", "label_3"]
See Hash methods
> ary = Hash.new
> ary[:item_1] = Hash[ :label => "label_1" ]
> ary[:item_2] = Hash[ :label => "label_2" ]
> ary[:item_3] = Hash[ :label => "label_3" ]
> ary.values.each {|v| puts v[:label]}
label_1
label_2
label_3
Given two hashes, I'm trying to replace a value in the first hash for a key that the second hash also has. To be specific, I have these two hashes:
data = {
"study" => "Lucid Study",
"name" => "Lucid Plan",
"studyWillBe" => "Combination"
}
conditions = { "study" => "((current))" }
I want data to have its "study" key updated since conditions has that key. I want data to end up like this:
data = {
"study" => "((current))",
"name" => "Lucid Plan",
"studyWillBe" => "Combination"
}
I got this far:
data = Hash[data.map {|k, v| [conditions[k] || k, v] }]
but that's not quite doing the trick. Can anyone point me in the right direction?
You can do this
data.each {|k, v| data[k] = conditions[k] if conditions[k]}
It's called merge.
data = {"study"=>"Lucid Study", "name"=>"Lucid Plan", "studyWillBe"=>"Combination"}
conditions = {"study"=>"((current))"}
data.merge(conditions)
#{"study"=>"((current))", "name"=>"Lucid Plan", "studyWillBe"=>"Combination"}
The method merge can take a block where you can make some specific operation not only assign new value
data.merge(conditions) do |key, oldvalue, newvalue|
newvalue
end
=> {"study"=>"((current))", "name"=>"Lucid Plan", "studyWillBe"=>"Combination"}
I'm trying to get the first key and value key from a hash table in ruby. I don't know the key values of the hash because it is passed to the method. I cant find anywhere online how to find the first key/value as a separate hash table.
I think hash[0] will just try to find an element with a name 0 it just returns nil when I run the code.
I know I can find the key name and the value and then create a new hash from them but i wonder if there is an easier way to do this so I get a hash right away.
here is my code:
def rps_game_winner(game)
rock_in_hash = game.invert['R']
paper_in_hash = game.invert['P']
scissors_in_hash = game.invert['S']
if(rock_in_hash)
if(paper_in_hash)
return paper_in_hash;
elsif(scissors_in_hash)
return rock_in_hash
end
elsif(paper_in_hash)
if(rock_in_hash)
return paper_in_hash
elsif(scissors_in_hash)
return scissors_in_hash
end
end
key = game.keys[-1]
value = game.values[-1]
winner = {key => value}
return winner
end
game_one = { "Bob" => 'P', "Jim" => 'P' }
puts rps_game_winner(game_one)
This gets me the correct result the problem is I don't understand why it's -1 instead of zero...
And i was hoping there was a better way to get the first key/value pair of a hash table instead of creating new hash table with the key and value you retrieved from the previous table.
You can just do
key, value = hash.first
or if you prefer:
key = hash.keys[0]
value = hash.values[0]
Then maybe:
new_hash = {key => value}
There is a shorter answer that does not require you to use extra variables:
h = { "a" => 100, "b" => 200 , "c" => 300, "d" => 400, "e" => 500}
Hash[*h.first] #=> {"a" => 100}
Or if you want to retrieve a key/value at a any single position
Hash[*h.to_a.at(1)] #=> {"b" => 200}
Or retrieve a key/values from a range of positions:
Hash[h.to_a[1,3]] #=> {"b"=>200, "c"=>300, "d"=>400}
[hash.first].to_h
Another way to do it.
my_hash = { "a" => "first", "b" => "second" }
{ my_hash.keys.first => my_hash.values.first }
This works too
I have a ruby hash that looks like this
{ "stuff_attributes" => {
"1" => {"foo" => "bar", "baz" => "quux"},
"2" => {"foo" => "bar", "baz" => "quux"}
}
}
and I want to turn it into a hash that looks like this
{ "stuff_attributes" => [
{ "foo" => "bar", "baz" => "quux"},
{ "foo" => "bar", "baz" => "quux"}
]
}
I also need to preserve the numerical order of the keys, and there is a variable number of keys. The above is super-simplified, but I've included a real example at the bottom. What's the best way to do this?
P.S
It also needs to be recursive
As far as the recursion goes, here's what we can assume:
1) the key that needs to be manipulated will match /_attributes$/
2) the hash will have many other keys that do not match /_attributes$/
3) the keys inside the hash will always be a number
4) an _attributes hash can be at any level of the hash under any other key
this hash is actually the params hash from a create action in the controller. This is a real example of what will need to be parsed with this routine.
{
"commit"=>"Save",
"tdsheet"=>{
"team_id"=>"43",
"title"=>"",
"performing_org_id"=>"10",
"tdsinitneed_attributes"=>{
"0"=>{
"title"=>"",
"need_date"=>"",
"description"=>"",
"expected_providing_organization_id"=>"41"
},
"1"=>{
"title"=>"",
"need_date"=>"",
"description"=>"",
"expected_providing_organization_id"=>"41"
}
},
"level_two_studycollection_id"=>"27",
"plan_attributes"=>{
"0"=>{
"start_date"=>"", "end_date"=>""
}
},
"dataitem_attributes"=>{
"0"=>{
"title"=>"",
"description"=>"",
"plan_attributes"=>{
"0"=>{
"start_date"=>"",
"end_date"=>""
}
}
},
"1"=>{
"title"=>"",
"description"=>"",
"plan_attributes"=>{
"0"=>{
"start_date"=>"",
"end_date"=>""
}
}
}
}
},
"action"=>"create",
"studycollection_level"=>"",
"controller"=>"tdsheets"
}
Note that this might be long to test if all keys are numbers before converting...
def array_from_hash(h)
return h unless h.is_a? Hash
all_numbers = h.keys.all? { |k| k.to_i.to_s == k }
if all_numbers
h.keys.sort_by{ |k| k.to_i }.map{ |i| array_from_hash(h[i]) }
else
h.each do |k, v|
h[k] = array_from_hash(v)
end
end
end
If we can assume that all the keys are in fact strings which convert cleanly to integers, the following ought to work:
# "hash" here refers to the main hash in your example, since you didn't name it
stuff_hash = hash["stuff"]
hash["stuff"] = stuff_hash.keys.sort_by {|key| key.to_i}.map {|key| stuff_hash[key]}
To take a bit of a liberty, I'm posting a very similar code example to Vincent Robert's.
This one is patches the Hash class with a .to_array method.
class Hash
def to_array(h = self)
return h unless h.is_a? Hash
if h.keys.all? { |k| k.to_i.to_s == k } # all keys are numbers so make an array.
h.keys.sort_by{ |k| k.to_i }.map{ |i| self.to_array(h[i]) }
else
h.each do |k, v|
h[k] = self.to_array(v)
end
end
end
end
It makes usage slightly more convenient.