Creating array of hashes in ruby - ruby

I want to create an array of hashes in ruby as:
arr[0]
"name": abc
"mobile_num" :9898989898
"email" :abc#xyz.com
arr[1]
"name": xyz
"mobile_num" :9698989898
"email" :abcd#xyz.com
I have seen hash and array documentation. In all I found, I have to do something
like
c = {}
c["name"] = "abc"
c["mobile_num"] = 9898989898
c["email"] = "abc#xyz.com"
arr << c
Iterating as in above statements in loop allows me to fill arr. I actually rowofrows with one row like ["abc",9898989898,"abc#xyz.com"]. Is there any better way to do this?

Assuming what you mean by "rowofrows" is an array of arrays, heres a solution to what I think you're trying to accomplish:
array_of_arrays = [["abc",9898989898,"abc#xyz.com"], ["def",9898989898,"def#xyz.com"]]
array_of_hashes = []
array_of_arrays.each { |record| array_of_hashes << {'name' => record[0], 'number' => record[1].to_i, 'email' => record[2]} }
p array_of_hashes
Will output your array of hashes:
[{"name"=>"abc", "number"=>9898989898, "email"=>"abc#xyz.com"}, {"name"=>"def", "number"=>9898989898, "email"=>"def#xyz.com"}]

you can first define the array as
array = []
then you can define the hashes one by one as following and push them in the array.
hash1 = {:name => "mark" ,:age => 25}
and then do
array.push(hash1)
this will insert the hash into the array . Similarly you can push more hashes to create an array of hashes.

You could also do it directly within the push method like this:
First define your array:
#shopping_list_items = []
And add a new item to your list:
#shopping_list_items.push(description: "Apples", amount: 3)
Which will give you something like this:
=> [{:description=>"Apples", :amount=>3}]

Related

Check if keys in a hashmap are all in an array

Say I have the array a = ["a","b"]
And the hashmap {"hello" => "world", "a" => "d"}
That would return false because "hello" is not in the array 'a'.
The hashmap: {"a" => "hello", "a" => "world"} is fine.
Is there a way to do this without manually doing all the work? eg: find if the hashmap keys are a subset of the array?
This will work:
(hash.keys - a).empty?
# if returns true means all keys present in array.
# if returns false means all keys are not present in array.
Try something like this:
keys = hashmap.keys
(keys - a).empty?
Is result 'keys - a' is empty - it means that all keys are in array
are you looking for this
a = ["a","b"]
b = {"hello" => "world", "a" => "d"}
(a-b.keys).empty?

ruby how to make a hash with new keys, and values from an array

I have an array of arrays like this:
arr = [["food", "eggs"],["beverage", "milk"],["desert", "cake"]]
And I need to turn it into an array of hashes where the keys are custom and new, and the values of the keys are the values in the array, like this:
hash = [{"category": "food", "item":"eggs"},
{"category": "beverage", "item":"milk"}
{"category": "desert", "item":"cake"}]
how would I do this?
thank you
Use Array#map:
arr = [["food", "eggs"], ["beverage", "milk"], ["desert", "cake"]]
arr.map { |category, item| { category: category, item: item } }
# => [
# {:category=>"food", :item=>"eggs"},
# {:category=>"beverage", :item=>"milk"},
# {:category=>"desert", :item=>"cake"}
# ]
arr = [["food", "eggs"],["beverage", "milk"],["desert", "cake"]]
arr.inject([]) do |hash, (v1, v2)|
hash << { category: v1, item: v2 }
end
I used inject to keep the code concise.
Next time you may want to show what you have tried in the question, just to demonstrate that you actually tried to do something before asking for code.
hash = array.map {|ary| Hash[[:category, :item].zip ary ]}
hash = arr.each_with_object({}){|elem, hsh|hsh[elem[0]] = elem[1]}

Clean way to search through hash keys in Ruby

I have a hash like so:
hash = {"jonathan" => "12", "bob" => 15 }
Then I have an array like so:
array = ['jon', 'bob']
I want to return the value of the key that includes a value in my array in the end.
The goal is something like this:
array.each do |name|
if hash.key.include? name
return hash.value
end
What's the best way to write that code block?
If you want multiple values, use Hash#values_at:
hash = {"jonathan" => "12", "bob" => 15 }
array = ['jon', 'bob']
hash.values_at(*array.select{|key| hash.has_key? key})
# => [15]
Using Array#&:
hash.values_at(*(hash.keys & array))
# => [15]
To get the keys, you don't need a block, this will do:
hash.keys & array
This takes the keys of the hash and intersect it with the array.
Second part, get a value from the hash:
hash[(hash.keys & array).last]
This will get the last key that is shared in hash and array and returns the value of that key in hash.
Also you can use select methods of Hash:
hash.select {| k,_ | array.include?( k ) }
# => {"bob"=>15}
and get, for example, last value:
hash.select {| k,_ | array.include?( k ) }.to_a.flatten.last
# => 15
or even use values_at method of Hash:
hash.values_at( *array ).compact.last
# => 15
Here is how I would write :
hash = {"jonathan" => "12", "bob" => 15 }
array = ['jon', 'bob']
array.collect(&hash.method(:[])).compact # => [15]

Ruby / Remove everything after a matched key / array of hashes

Let's say I have the following array of hashes:
h = [{"name" => "bob"}, {"car" => "toyota"}, {"age" => "25"}]
And I have the following key to match:
k = 'car'
How do I match the 'k' to 'h' and have delete every element after the match so that it returns:
h = [{"name" => "bob"}, {"car" => "toyota"}]
Just convert hash to array, do your task and then convert back
h = {"name" => "bob", "car" => "toyota", "age" => "25"}
array = h.to_a.flatten
index = array.index('car') + 1
h = Hash[*array[0..index]]
=> {"name"=>"bob", "car"=>"toyota"}
By the way, the hash is ordered only since Ruby 1.9
ar = [{"name" => "bob"}, {"car" => "toyota"}, {"age" => "25"}]
p ar[0 .. ar.index{|h| h.key?('car')}] #=>[{"name"=>"bob"}, {"car"=>"toyota"}]
I like megas' version, as its short and to the point. Another approach, which would be more explicit, would be iterating over the keys array of each hash. The keys of a hash are maintained in an ordered array (http://ruby-doc.org/core-1.9.3/Hash.html). They are ordered by when they were first entered. As a result, you can try the following:
newArray = Array.new
h.each do |hash| # Iterate through your array of hashes
newArray << hash
if hash.has_key?("car") # check if this hash is the "car" hash.
break # exits the block
end
end
This all depends, of course, on whether the array was created in the proper order. If it was, then you're golden.
A hash is unordered set by definition, so what you request is somewhat undefined. However you can do something like a hack:
h = {"name" => "bob", "car" => "toyota", "age" => "25"}
matched = false
key_given = "car"
h.each do |k,v|
if matched
h.delete(k)
end
if k == key_given
matched = true
next
end
end
I'm pretty late to the party here. I was looking for a solution to this same problem, but I didn't love these answers. So, here's my approach:
class Array
def take_until(&blk)
i = find_index &blk
take(i + 1)
end
end
h = [{"name" => "bob"}, {"car" => "toyota"}, {"age" => "25"}]
k = 'car'
h.take_until { |x| x.has_key?(k) }
=> [{"name"=>"bob"}, {"car"=>"toyota"}]

Finding hashes with items from the array using ruby

Sorry for missunderstanding for my fault I didn't check class of item...
I have an array:
array = [link1, link2, link3, link4, etc]
and array_of_hashes with two items: names and links
hash = [ :names, :links ] e.g.
array_of_hashes = [{ :names => name1, :links => link1}, {:names = name2, :links => link2}, ... ]
I want to do something with each pair of items from array_of_hashes which includes links from the array.
UPD: Revised data... sorry for missunderstanding.
It was a bit vague of a question but here is a shot at it.
you will need to reorder what you're trying to access from the hash, unless :name is required.
arr = ["link0", "link1",..."linkN"]
hsh = { "link0", item0, "link1", item1, "link1", item2,..."linkN", itemN}
hsh.each_pair | link, item |
do_something_foo(item) if arr.include?(link) # do_something_foo is a predefined function
end
jagga99 wrote
I want to do something with each item from hash which contain links from the array. Thanks a lot for your help.
If the [:name, :link] is the require pair, then you would need to identify which part is the item to do something with: the name or the link.
Enumerate the array of hashes and search the link array.
array = [:link1, :link2, :link3]
array_of_hashes = [{ :names => :name1, :links => :no_link}, {:names => :name2, :links => :link2}]
array_of_hashes.each do |hash|
if array.any? {|s| s==hash[:links]}
puts "Do something with #{hash[:names].to_s}"
end
end

Resources