sort ruby hash by specific key - ruby

I have a ruby hash like this
{"id"=>62, "name"=>"Wine and Spirits"}
{"id"=>63, "name"=>"Tobacco"}
{"id"=>64, "name"=>"Printing"}
{"id"=>65, "name"=>"Information Services"}
{"id"=>66, "name"=>"Business Supplies and Equipment"}
How do I sort this by name? I tried
categories.sort_by {|_key, value, _key1, value1| value1}
But that did not work

Assuming you want to sort an array of hashes:
def sort_by_name(hashes)
hashes.sort_by { |h| h["name"] }
end

Related

How can I get the values of hash using a key array?

I want to get all value of a hash using an array containing the keys?
I have this hash:
{:id=>402, :email=>"tyson#ledner.name", :organizations_count=>0, :username=>"admin"}
I have an array :
[:id, :email]
So I want to get an array of
["402", "tyson#ledner.name"]
Is there a cleaver way to do this? I have a loop but I feel ruby can do this in a "oneliner" way but can figure out how to do this.
You should use Hash#values_at:
hash = {:id=>402, :email=>"tyson#ledner.name", :organizations_count=>0, :username=>"admin"}
array = [:id, :email]
hash.values_at(*array)
#=> [402, "tyson#ledner.name"]
Passing array with splat operator (*) as argument in this case is same as just hash.values_at(:id, :email)

Hash Parsing with Ruby

I have the array of hash as shown below:
#line_statuses = [
{:name=>"1", :status=>"online"},
{:name=>"2", :status=>"online"}
]
I'd like to parse each hash inside of #line_statuses array so that I can print out the name and status as shown below.
1: online
2: online
How would I go about doing this?
Technically your #line_statuses variable is an array, so what you have is an array of hashes. In Ruby, to iterate over an array we use the .each method. Then, in each iteration, we can access the values of the hash using the defined keys:
#line_statuses.each do |hash|
puts hash[:name]
puts hash[:status]
end
So simple...:
#line_statuses.each do |line_status|
puts "#{line_status[:name]}: #{line_status[:status]}"
end
try #line_statuses.each{|i| puts i[:name],i[:status]}
Pretty simple:
#line_statuses.each { |line_status| puts "#{line_status[:name]}: #{line_status[:status]}" }

Sort array of hash in ruby

I have an array of hash like this:
[{683=>5}, {689=>2}, {692=>10}]
I want the result like this:
[{692=>10}, {683=>5}, {689=>2}]
Could any one help me?
Use Enumerable#sort_by. The return value of the block is used as comparison key.
[{683=>5}, {689=>2}, {692=>10}].sort_by { |h| -h.values[0] }
# => [{692=>10}, {683=>5}, {689=>2}]

How do I subgroup this hash that has already been grouped?

I have a set of word strings which I am turning into a hash, grouped by the size of the string. I am doing this by:
hash = set.group_by(&:size)
resulting in
hash = {5=>[apple, andys, throw, balls], 7=>[bananas, oranges]}
I want to further group the hash values by first letter, so the the end results looks like:
hash = {5=>{a=>[apple, andys],b=>[balls],t=>[throw]}, 7=>{b=>[bananas], o=>[oranges]}}
I tried putting
hash.each_value do | value |
value = value.group_by(&:chr)
end
after the first group_by but that only seems to return the original hash. I am admittedly a ruby beginner so I'm not sure if I could do this in one fell swoop, or exactly how (&:size) notation works, if I were asked to write it out. Thoughts?
To update your hash you need to do like this
hash.each do |key, value|
hash[key] = value.group_by(&:chr)
end
I'd keep the whole computation functional:
>> Hash[set.group_by(&:size).map { |k, vs| [k, vs.group_by(&:chr)] }]
=> {5=>{"a"=>["apple", "andys"], "t"=>["throw"], "b"=>["balls"]},
7=>{"b"=>["bananas"], "o"=>["oranges"]}}

Delete array of keys in Ruby Hash

How would I go about deleting an array of keys in a hash? For example, you can call:
hash.delete(some_key)
But how can I do this:
hash.delete([key1,key2,key3,...])
without needing to looping manually.
You can iterate over an array of keys and delete everyone of them:
[key1, key2, key3].each { |k| some_hash.delete k }
Can't remember any better solution.
This is exactly what you are looking for...
You can do it like this without looping through the array unnecessarily.
keys_to_delete = [key1, key2, key3]
hash_array.except!(*keys_to_delete)
The result is stored in hash_array
You can try to use Hash#delete_if:
delete_if deletes every key-value pair from hsh for which block evaluates to true.
array_hash.delete_if { |key, _| [key1, key2, key3].include? key }
UPDATE
If you don't want to iterate over array of keys, you can use Set instead of Array (since Set uses Hash as storage include? is O(1)):
require 'set'
keys = [key1,key2,key3].to_set
array_hash.delete_if { |key, _| keys.include? key }
Maybe it's worth to make a method
class Hash
def delete_by_keys *keys
keys.each{|k| delete(k)}
end
end
hash_array.delete_by_keys(key1,key2,..)
ActiveSupport (part of Rails) implements exactly this, as Hash#except and Hash#except!
def except!(*keys)
keys.each { |key| delete(key) }
self
end
See http://apidock.com/rails/v4.0.2/Hash/except%21

Resources