Ruby Array to Hash: Each Element the Key and Derive Value from It

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



Leave a reply



Submit