Ruby array to hash: each element the key and derive value from it
Ruby's each_with_object
method is a neat way of doing what you want
['a', 'b'].each_with_object({}) { |k, h| h[k] = k.upcase }
Ruby convert an Array to Hash values with specific keys
You can use #zip
your_array = ["12", "21", "1985"]
keys = ['month', 'day', 'year']
keys.zip(your_array).to_h
Get a value from an array of hashes in ruby
The select statement will return all the hashes with the key 13.
If you already know which hash has the key then the below code will give u the answer.
ary[1][13]
However if you are not sure which of your hashes in the array has the value, then you could do the following:
values = ary.map{|h| h[13]}.compact
Values will have the value of key 13 from all the hashes which has the key 13.
Collect specific values from an array of hashes
A Hash is a dictionary-like collection of unique keys and their values. Also called associative arrays, they are similar to Arrays, but where an Array uses integers as its index, a Hash allows you to use any object type.
Of course, a value can be any object - string, method, nil, number, object. So, only after create, we can know that is saved in our hash. For this reason when trying to get all key:
data.keys # => ["etag", "items"]
There is no any nested key. So finding value by missing key return nil
.
To select all videoId you must do something like this:
data["items"].map { |item| item["snippet"]["resourceId"]["videoId"] }.compact
Also, you can update Hash class as there:
class Hash
def deep_find(key, object=self, found=nil)
if object.respond_to?(:key?) && object.key?(key)
return object[key]
elsif object.is_a? Enumerable
object.find { |*a| found = deep_find(key, a.last) }
return found
end
end
end
And then run
data["items"].map { |item| item.deep_find('videoId') }
That method avoids the error when the json will have a variable structure.
Convert array of hashes to single hash with values as keys
This should do what you want
countries.each_with_object({}) { |country, h| h[country[:country].to_sym] = country[:cost] }
=> {:england=>12.34, :scotland=>56.78}
In Ruby, compare an array and hash function and if the key matches the array element return/replace it with the value of the key
You could map each word in the sentence, and try to access the replacement_words hash for each word, if you can get the value for a specific key, then you're done, if not, then you use the same word:
replacement_words = {
'hello' => 'hola',
'two' => 'dos',
'goodbye' => 'adios',
'ten' => 'diez',
'4' => 'cuatro',
'house' => 'casa',
'cat' => 'gato'
}
sentence = 'Hola it has been dos days since your gato has visited my casa'
p sentence.split.map { |word| replacement_words[word.downcase] || word }.join(' ')
# "hola it has been dos days since your gato has visited my casa"
Since Hello isn't in the replacement_words then it won't get the value, but you can downcase the word, which would make the sentence apply the key as it's in the hash.
Create a hash out of an array where the values are the indices of the elements
I'm adding my two cents:
array = [1,3,4,5,6,6,6,8,8,8,9,7,7,7]
hash = {}
array.map.with_index {|val, idx| [val, idx]}.group_by(&:first).map do |k, v|
hash[k] = v[0][1] if v.size == 1
hash[k] = v.map(&:last) if v.size > 1
end
p hash #=> {1=>0, 3=>1, 4=>2, 5=>3, 6=>[4, 5, 6], 8=>[7, 8, 9], 9=>10, 7=>[11, 12, 13]}
It fails with duplicated element not adjacent, of course.
This is the expanded version, step by step, to show how it works.
The basic idea is to build a temporary array with pairs of value and index, then work on it.
array = [1,3,4,5,6,6,6]
tmp_array = []
array.each_with_index do |val, idx|
tmp_array << [val, idx]
end
p tmp_array #=> [[1, 0], [3, 1], [4, 2], [5, 3], [6, 4], [6, 5], [6, 6]]
tmp_hash = tmp_array.group_by { |e| e[0] }
p tmp_hash #=> {1=>[[1, 0]], 3=>[[3, 1]], 4=>[[4, 2]], 5=>[[5, 3]], 6=>[[6, 4], [6, 5], [6, 6]]}
hash = {}
tmp_hash.map do |k, v|
hash[k] = v[0][0] if v.size == 1
hash[k] = v.map {|e| e[1]} if v.size > 1
end
p hash #=> {1=>1, 3=>3, 4=>4, 5=>5, 6=>[4, 5, 6]}
It can be written as one line as:
hash = {}
array.map.with_index.group_by(&:first).map { |k, v| v.size == 1 ? hash[k] = v[0][1] : hash[k] = v.map(&:last) }
p hash
Ruby problem with returning hash value from an array of hashes
After reading your edited question, I see that there are a few conditions that weren't met with previous answers. I also see the main flaw in your code. Let's start with the flaw:
Your code seems a little overly complicated but it should work just fine if you make this one small change to the 5th line of the following section;
def find_favorite(array_of_hash_objects)
array_of_hash_objects.each do | hash |
hash.each do |key, val|
if key == :is_my_favorite? && val == true
return hash
end
end
end
return nil
end
Notice that I prepended the line with return
. Your problem was that you were iterating through the array just fine but there was no container or method being initiated in order to store or return those results. Your second to last line was telling the method to return nil no matter what the results of the iteration were.
Now for my proposed solution:
I see now that your desired output should either be the single hash containing the true
value or should be nil
as opposed to the arrays resulting from the solutions mentioned above. I would probably do something like this;
def find_favorite(input)
output = nil
input.each{|h| h[:is_my_favorite?] ? output = h : nil}
output
end
arr_1 = [{ name: 'Ruby', is_my_favorite?: true }, { name: 'JavaScript', is_my_favorite?: false }, { name: 'HTML', is_my_favorite?: false }]
arr_2 = [{ name: 'Ruby', is_my_favorite?: false }, { name: 'JavaScript', is_my_favorite?: false }, { name: 'HTML', is_my_favorite?: false }]
find_favorite(arr_1) #=> {:name=>"Ruby", :is_my_favorite?=>true}
find_favorite(arr_2) #=> nil
Within the method definition, a container (output
) is first defined with a default value of nil
. We then iterate through the array and fill output
with the hash containing a true value. Otherwise output
returns the default value.
NOTE: You could optionally delete == true ?
from the block but seeing as how I don't know how the original array is being created, I prefer to leave it in there to expressly communicate exactly what I'm looking for in a very human readable way. That's just my personal preference.
Convert Array to Hash while preserving Array index values in Ruby
Using Enumerable#each_with_index
:
Hash[array.each_with_index.map { |value, index| [index, value] }]
# => {0=>"Adult", 1=>"Family", 2=>"Single", 3=>"Child"}
As @hirolau commented, each_with_index.map
can also be written as map.with_index
.
Hash[array.map.with_index { |value, index| [index, value] }]
# => {0=>"Adult", 1=>"Family", 2=>"Single", 3=>"Child"}
UPDATE
Alterantive that use Hash#invert
:
Hash[array.map.with_index{|*x|x}].invert
# => {0=>"Adult", 1=>"Family", 2=>"Single", 3=>"Child"}
Hash[[*array.map.with_index]].invert
# => {0=>"Adult", 1=>"Family", 2=>"Single", 3=>"Child"}
Related Topics
How to Print Something Without a New Line in Ruby
Collecting Hashes into Openstruct Creates "Table" Entry
Problem When Installing Ruby 2.2.9 on MAC Big Sur M1
Retrieving Image Height with Carrierwave
Testing Simple Sti with Factorygirl
No Source for Ruby-2.0.0-P451 Provided with Debugger-Ruby_Core_Source Gem
Running Webrick Server in Background
Ruby on Rails - Paperclip and Dynamic Parameters
Rails Pass Params/Arguments to Activerecord Callback Function
How to Set a Request.Referrer Inside My Rspec
What Grammar Based Parser-Generator Tools Exist for Ruby
"Gem Update --System Is Disabled on Debian" Error
Memorable Name Generator Gem for Ruby
Marking an Unused Block Variable