Collect a hash of arrays in ruby - ruby

h = {1=>[1,2,3], 2=>[4,5,6]}
new_arr = []
h.each_value {|arr|
new_arr.concat(arr)
}
This works, but what's a more ruby-like way to do it?
All values are arrays but the elements of each array should not be modified.

How's about this?
h.values.flatten

You can use reduce:
h.values.reduce(&:+)

Slightly cryptic
h.flat_map(&:last)
Slightly verbose
h.flat_map{|_, value| value}

If you want to get the array of hash value, use Hash#values.
new_arr = h.values

Related

ruby - help need to convert an array to a specific type of array of arrays, duplicating the keys as [key, value] int he list

I want to convert and array into a specific type of array of arrays.
array = ["Project", "Publication"]
into
array_of_arrays =[["Project", "Project"], ["Publication", "Publication"] ]
The array is not just limited to size two. Its a growing list , so looking for some function to convert it to array_of_arrays.
Appreciate any help.
def replicate(arr, n)
arr.map { |e| [e]*n }
end
replicate(["Project", "Publication"], 2)
#=> [["Project", "Project"], ["Publication", "Publication"]]
replicate(["Project", "Publication"], 3)
#=> [["Project", "Project", "Project"], ["Publication", "Publication", "Publication"]]
replicate([["ProjectA", "ProjectB"], "Publication"], 2)
#=> [[["ProjectA", "ProjectB"], ["ProjectA", "ProjectB"]], ["Publication", "Publication"]
This is something map can handle quite easily.
a = ["Project", "Publication"]
a.map{|x| [x,x]}
#=> [["Project", "Project"], ["Publication", "Publication"]]

Array of paths from Nested Hash

I have a hash
my_hash = {"key1"=> {"key2"=> {"key3"=> "value"}}, "key4"=> "value"}
I want to return only the full path of the keys as an array. All concatenated like this
[key1, key1key2, key1key2key3, key4].
Any suggestions on how to do this. Thanks
I've been able to solve this with the iteraptor helpers suggested by this user. Thanks
I used the feature 'aplanar' i.e
hash.aplanar.keys
returns the paths of all the keys that have values. Just as I wanted.
The following is a recursive method that progressively modifies the keys of inner hashes. For example,
{"key2"=> {"key3"=> "value"}}
is changed to
{"key1key2"=> {"key3"=> "value"}}
after which
{"key3"=> "value"}
is changed to
{"key1key2key3"=> "value"}
This allows me to simply accumulate the keys of these hashes.
def recurse(h)
h.map do |k,v|
next k unless v.is_a?(Hash)
key, val = v.flatten
[k, recurse("#{k}#{key}"=>val)]
end.flatten
end
recurse my_hash
#=> ["key1", "key1key2", "key1key2key3", "key4"]

Ruby - hash to array

I have:
a = [{"_id"=>BSON::ObjectId('569a58b8e301d083c300000c')}]
and I want it to be:
[BSON::ObjectId('569a58bee301d083c3000752')]
I was experimenting with
a.map{|e| e.map{|k, v| v }}
but it gives me nested array:
[[BSON::ObjectId('569a58b8e301d083c300000c')]]
I'll appreciate any help.
If you just had a hash:
h = {"_id"=>BSON::ObjectId('569a58b8e301d083c300000c')}
and you wanted to fetch the BSON::ObectId, you would call Hash#[]:
h["_id"] #=> BSON::ObjectId('569a58b8e301d083c300000c')
The same works with map:
a.map { |h| h["_id"] }
#=> [BSON::ObjectId('569a58b8e301d083c300000c')]
A cleaner solution.
a = [{"id"=>"1234"},{"id"=>"9876"}]
a.flat_map(&:values)
=> ["1234", "9876"]
I'd use values, then call flatten.
a.collect(:&values).flatten
Or, if there'll only ever be one value
a[0].values[0]

Converting hash to array of hashes order preserved?

I have a hash h:
h = {145=>1, 137=>2, 34=>3}
I want to convert it into an array of hashes of the form:
[{cid:145, qty:1}, {cid:137, qty:2}, {cid:34, qty:3}]
My first attempt a solution works for this example:
h.keys.zip(h.values).map { |cid, qty| {cid:cid, qty:qty} }
Evaluates to
[{:cid=>145, :qty=>1}, {:cid=>137, :qty=>2}, {:cid=>34, :qty=>3}]
My worry is that h.keys and h.values won't always align, since hashes aren't necessarily ordered.
How can I solve this problem with the guarantee that the keys of h will be paired with their corresponding values?
h = {145=>1, 137=>2, 34=>3}
h.map!{ |k, v| {:cid =>k, :qty => v} }

How to iterate over array of hashes and hash with smallest attribute

I've got an array of hashes and I need to figure out which hash has the smallest height attributes. So given this array,
[{"height"=>130, "source"=>"http.facebook.com/tiny_pic.jpg", "width"=>173},
{"height"=>1230, "source"=>"http.facebook.com/giant_pic.jpg", "width"=>1273}]
I want to return this
{"height"=>130, "source"=>"http.facebook.com/tiny_pic.jpg", "width"=>173}
What's the most efficient way to do this?
Sure it's just an array so:
array_of_hashes.min_by {|h| h['height']}
Use the min method:
hash = array.min { |a,b| a['height'] <=> b['height'] }

Resources