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

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'] }

Related

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"]

How can I turn an array of keys into an array of values?

I have a hash like
hash = { 'burger': 2, 'kebab': 5, 'pizza': 10 }
and I have an array of its keys like
['burger', 'burger', 'pizza']
How would I create an array of the corresponding values? Would inject method be the best method to sum value array together?
Actually, you don't even need to prepare the key arrays.
To get the keys: hash.keys
To get the values: hash.values
If you want only certain values or values in certain order, then
a = [:burger, :pizza]
hash.values_at(*a) # => [2, 10]
You can use map as you've particularly said of wanting value of particular key in an array in a particular order. Else, you can use hash.values
arr = ['burger', 'burger', 'pizza']
results = arr.map { |key| hash[key] }

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} }

Collect a hash of arrays in 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

Ruby: sort array of hashes, even though key may not exist

In a rails application, I have an array of hashes which I can sort easily with just
array_of_hashes.sort_by { |hash| hash[:key_to_sort] }
But what if not every array member has a key :key_to_sort? Then the sort will fail "comparison of String with nil failed". Is there a way to allow the sort to continue? Or is there another way to do this?
It depends what you want to do when a hash doesn't have sorting key. I can imagine two scenarios:
1) exclude the hash from sorting
arr.delete_if { |h| h[:key_to_sort].nil? }.sort_by { |h| h[:key_to_sort] }
2) place the hash at the beginning/end of the array:
arr.sort_by { |h| h[:key_to_sort] || REALLY_SMALL_OR_LARGE_VALUE }

Resources