Array to Hash Ruby
a = ["item 1", "item 2", "item 3", "item 4"]
h = Hash[*a] # => { "item 1" => "item 2", "item 3" => "item 4" }
That's it. The *
is called the splat operator.
One caveat per @Mike Lewis (in the comments): "Be very careful with this. Ruby expands splats on the stack. If you do this with a large dataset, expect to blow out your stack."
So, for most general use cases this method is great, but use a different method if you want to do the conversion on lots of data. For example, @Łukasz Niemier (also in the comments) offers this method for large data sets:
h = Hash[a.each_slice(2).to_a]
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"}
Convert an array to hash, where keys are the indices
arr = ["one", "two", "three", "four", "five"]
x = Hash[(0...arr.size).zip arr]
# => {0=>"one", 1=>"two", 2=>"three", 3=>"four", 4=>"five"}
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.
transform array of arrays in array of hash
array = [
[ 1, "name1" ],
[ 2, "name2" ],
[ 3, "name3" ],
[ 4, "name4" ]
]
array.map { |e| ['id', 'name'].zip(e).to_h }
#⇒ [
# {"id"=>1, "name"=>"name1"},
# {"id"=>2, "name"=>"name2"},
# {"id"=>3, "name"=>"name3"},
# {"id"=>4, "name"=>"name4"}
# ]
The only interesting here is Enumerable#zip
, that “merges” arrays.
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
Adding new keys to a Array Of Hashes
I would probably:
- Use
map
to iterate over the elements inlist
and build a new array at the same time - Since each element is a hash with one item, destruct that into a key and value
- Build the new hash in the correct format
new_list = list.map do |hash|
# e.g. key = "Mary", value = "Die Hard"
key, value = hash.first
{name: key, film: value}
end
This assumes that each hash in the list will have only one item (as you've shown in your example in the question) - you may want to validate this elsewhere, since this solution would ignore any other items in the hash past the first.
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 }
Related Topics
I Want to Return a Single Result Using .Find() with Ruby on Rails
Ruby: Append Text to the 2Nd Line of a File
Illegal Quoting in Line 1 Using Ruby CSV
Why Rails Instance Method Can Be Used as Class Method in Rspec
Duplicate Elements of Array in Ruby
Error Loading the 'Sqlite3' Active Record Adapter. When I Deploy in Heroku
How to Condense Summable Metrics to a Unique Identifier in a Ruby Table
How to Use 'Debugger' and 'Pry' When Developing a Gem? (Ruby)
Selenium Webdriver Take Screenshot of Viewport Only
Why Must I Explicitly Call Self on Accessor When Using the Array Union Operator |= in Ruby
Implementing Dry-Run in Ruby Script
Rails Activerecord: Saving Nested Models Is Rolled Back
Check If a Table Exists in Rails
Capistrano Deploy Fails After I Changed the Repository Url