Ruby: select a hash from inside an array - ruby

I have the following array:
response = [{"label"=>"cat", "name"=>"kitty", "id"=>189955}, {"label" => "dog", "name"=>"rex", "id" => 550081}]
How do I select the hash that contains the label cat? I know response.first will give me the same result, but I want to search the by label.
Thanks!
Deb

response.find {|x| x['label'] == 'cat' } #=> {"label"=>"cat", "name"=>"kitty", "id"=>189955}

Try:
response.select { |x| x["label"] == "cat" }

Related

Modifying an Array

I have an Array like this
example_array = ['dog', 'cat', 'snake']
And I am trying to append the timestamp to each element of the array and the output should look like
example_array = [{'dog': 'time_stamp'},{'cat':'time_stamp'},{'snake':'time_stamp'}]
I've tried this but the output is incorrect:
a = {}
example_array.each_with_index do |element, i|
a.merge!("#{element}": "#{Time.now}")
example_array.delete_at(i)
end
Can anyone suggest me a solution in ruby?
I have tried a lot of ways but couldn't obtain the output like above.
Aditha,
How about this?
array = ["cat", "hat", "bat", "mat"]
hash = []
hash.push(Hash[array.collect { |item| [item, Time.now] } ])
OUTPUT: => [{"cat"=>"2018-02-28 04:23:08 UTC", "hat"=>"2018-02-28 04:23:08 UTC", "bat"=>"2018-02-28 04:23:08 UTC", "mat"=>"2018-02-28 04:23:08 UTC"}]
Instead of item.upcase you would insert your timestamp info. It gives me hashes inside of array.
example_array.product([Time.now]).map { |k,v| { k.to_sym=>v }}
#=> [{:dog=>2018-02-27 20:42:56 -0800},
# {:cat=>2018-02-27 20:42:56 -0800},
# {:snake=>2018-02-27 20:42:56 -0800}
]Note this ensures that all values (timestamps) are equal.
only weird thing is that you have to use => instead of :
arr = ['dog', 'cat', 'snake']
arr2 = []
for index in 0 ... arr.size
arr2.push({arr[index] => Time.now})
end
puts arr2
['dog', 'cat', 'snake'].map{|e| [{e.to_sym => "time_stamp"}]}
# => [[{:dog=>"time_stamp"}], [{:cat=>"time_stamp"}], [{:snake=>"time_stamp"}]]

ruby set key of hash for array of hashes

Given the following array of hashes, how can I make a new hash with friend_id as the key and dist the value?
results = [
{"user_id"=>"18", "friend_id"=>"17", "dist"=>"1"},
{"user_id"=>"18", "friend_id"=>"42", "dist"=>"1"},
{"user_id"=>"18", "friend_id"=>"43", "dist"=>"1"},
{"user_id"=>"18", "friend_id"=>"46", "dist"=>"2"}
]
desired_hash = {"17" => "1", "42" => "1", "43" => "1", "46" => "2"}
I've tried map but the values are then in an array. I also tried to flatten that result but it flattened the key instead of the value
results.each_with_object({}) { |g,h| h[g["friend_id"]] = g["dist"] }
or
results.each_with_object({}) { |g,h| h.update(g["friend_id"]=> g["dist"]) }
For this use case, I think it would be simpler and more readable to just use #each:
desired_hash = Hash.new
results.each {|h| desired_hash[h["friend_id"]] = h["dist"]}
Then, desired_hash is:
#=> {"17"=>"1", "42"=>"1", "43"=>"1", "46"=>"2"}
You can use Enumerable#inject method.
results.inject({}) {|sum, e| sum.merge({e["friend_id"] => e["dist"]})}
# => {"17"=>"1", "42"=>"1", "43"=>"1", "46"=>"2"}
results.map {|h| [h['friend_id'], h['dist']]} .to_h
Although I probably like #CarySwoveland 's answer better, on the lines of:
results.each_with_object({}) {|h, n| n[h['friend_id']] = h['dist']}
Simply:
desired_hash = Hash[results.map{ |h| [ h['friend_id'], h['dist']] }]
or as Victor suggests
desired_hash = Hash[results.map{ |x| x.values_at('friend_id', 'dist') }]

Converting an array of strings into a key-value pair

I have an array as the value of a hash:
:params=>[":centre_id", ":id"]
I am trying to find a way to convert each element of the array to something like this:
:centre_id => 1
:id => 1
I tried loads of different ways but I can't seem to find a nice clean way to do it:
"#{route[:params].map {|x| x.parameterize.underscore.to_sym => '1'}}"
This is what I am trying to achieve:
-{"controller"=>"venues", "action"=>"activity, {:centre_id=>1, :id=>1}"}
+{"controller"=>"venues", "action"=>"activity", "centre_id"=>"1", "id"=>"1"} << this one
string or symbol doesn't matter does it?
Using this:
expect(route[:request_method] => route[:path]).to route_to "#{route[:controller]}##{route[:action]}, #{Hash[route[:params].map {|x| [x.sub(/\A:/,'').to_sym, 1] }]}"
Help would be much appreciated.
Do as below :-
Ruby 2.1 or above, use below :-
route[:params].map {|x| [x.sub(/\A:/,'').to_sym, 1] }.to_h
# => {:centre_id => 1, :id => 1}
Ruby 2.0 or below, use below :-
Hash[route[:params].map {|x| [x.sub(/\A:/,'').to_sym, 1] }]
# => {:centre_id => 1, :id => 1}
If
h = { :params=>[":centre_id", ":id"], :animals=>[":dog", ":cat", ":pig"] }
one of the following may be helpful:
h.merge(h) { |_,v,_| Hash[v.map { |s| [s[1..-1].to_sym,1] }] }
#=> {:params=>{:centre_id=>1, :id=>1}, :animals=>{:dog=>1, :cat=>1, :pig=>1}}
or
Hash[h.keys.map { |k| h.delete(k).map { |s| [s[1..-1].to_sym,1] } }.flatten(1)]
#=> {:centre_id=>1, :id=>1, :dog=>1, :cat=>1, :pig=>1}
The second modifies h. If you don't want that to happen, you'll need to h.dup first.
If a is an array, you can replace Hash[a] with a.to_h with Ruby 2.1+.

How to print only a value in key value pair

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.

How do you replace a string with a hash collection value in Ruby?

I have a hash collection:
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
What syntax would I use to replace the first occurrence of the key with hash collection value in a string?
eg my input string:
str = I want a 3
The resulting string would be:
str = I want a cat
My one liner:
hash.each { |k, v| str[k] &&= v }
or using String#sub! method:
hash.each { |k, v| str.sub!(k, v) }
"I want a %{b}" % {c: "apple", b: "bee", a: "cat"}
=> "I want a bee"
Assuming Ruby 1.9 or later:
str.gsub /\d/, my_hash
I didn't understand your problem, but you can try this:
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
str = "I want a 3"
str.gsub(/[[:word:]]+/).each do |word|
my_hash[word] || word
end
#=> "I want a cat"
:D
Just to add point free style abuse to fl00r's answer:
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
my_hash.default_proc = Proc.new {|hash, key| key}
str = "I want a 3"
str.gsub(/[[:word:]]+/).each(&my_hash.method(:[]))
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
str = "I want a 3"
If there isn't any general pattern for the strings you want to substitute, you can use:
str.sub /#{my_hash.keys.map { |s| Regexp.escape s }.join '|'}/, my_hash
But if there is one, the code becomes much simpler, e.g.:
str.sub /[0-9]+/, my_hash
If you want to substitute all the occurrences, not only the first one, use gsub.
You can use String.sub in ruby 1.9:
string.sub(key, hash[key])
The following code replace the first occurrence of the key with hash collection value in the given string str
str.gsub(/\w+/) { |m| my_hash.fetch(m,m)}
=> "I want a cat"

Resources