Ruby group hashes by value of key
array.group_by {|x| x['type']}
or if you want the symbol key things you could even
array.group_by {|x| "type_#{x['type']}".to_sym}
I think this best expresses "So basically each array of hashes would be grouped by the value of its type key, and then returned as a hash with an array for each type", even if it leaves the :type
key alone in the output hashes.
Group Hash by values in ruby
You can group hash by its value:
h1 = {
"admin_milestones"=>"1",
"users_milestones"=>"0",
"admin_goals"=>"1",
"users_goals"=>"0",
"admin_tasks"=>"1",
"users_tasks"=>"0",
"admin_messages"=>"1",
"users_messages"=>"0",
"admin_meetings"=>"1",
"users_meetings"=>"0"
}
h2 = h1.group_by{|k,v| v}
It will produce a hash grouped by its values like this:
h2 = {"1"=>[["admin_milestones", "1"], ["admin_goals", "1"], ["admin_tasks", "1"], ["admin_messages", "1"], ["admin_meetings", "1"]],
"0"=>[["users_milestones", "0"], ["users_goals", "0"], ["users_tasks", "0"], ["users_messages", "0"], ["users_meetings", "0"]]}
Group array of hashes by key
Use group_by
.
array.group_by{|h| h[:user]}.values
Ruby group hashes based on matching keys and store the value of non matching keys in an array
You can try grouping by key
and value
and then map the revenue
values:
foos
.group_by { |e| e.values_at(:key, :value) }
.map do |(key, value), values|
{ key: key, value: value, revenue: values.map { |e| e[:revenue] } }
end
# [{:key=>"Foo", :value=>1, :revenue=>[2, 4]}, {:key=>"Bar", :value=>2, :revenue=>[7]}, {:key=>"bar", :value=>2, :revenue=>[9]}, {:key=>"Zampa", :value=>4, :revenue=>[9]}]
Ruby hash group by value
I would do something like this:
student_marks.group_by { |k, v| v }.map { |k, v| [k, v.map(&:first)] }.to_h
#=> { 50 => ["Alex", "Matt"], 54 => ["Beth"]}
i want to make a group Hash by keys and add values
I'd use the each_with_object
method.(key, value)
here is a deconstruction of each key/value pair like 93=>1
, hash
is an intermediate object to store the result.
data.each_with_object({}) do |(key, value), hash|
result_key =
case key
when 10..19 then 1
when 20..29 then 2
when 90..99 then 9
end
next if result_key.nil?
hash[result_key] ||= 0
hash[result_key] += value
end
For the provided input I got {9=>2, 2=>7856, 1=>267}
UPD
A shorter solution suggested by Holger Just and Stefan in the comments below.
data.each_with_object(Hash.new(0)) do |(key, value), hash|
hash[key / 10] += value
end
With Hash.new(0)
the initial object will be a hash with the default value 0
> hash = Hash.new(0)
=> {}
> hash[1]
=> 0
Ruby group array of hashes by numeric key
Injecting into a default hash:
arr = [{1=>6}, {1=>5}, {4=>1}]
arr.inject(Hash.new{|h,k| h[k]=[]}){|h, e| h[e.first[0]] << e.first[1]; h}
# => {1=>[6, 5], 4=>[1]}
Or, as suggested in the comments:
arr.each.with_object(Hash.new{|h, k| h[k] = []}){|e, h| h[e.first[0]] << e.first[1]}
# => {1=>[6, 5], 4=>[1]}
Group by specific array value in hash and include key
Using #each_with_object
to build up a hash as we iterate over the keys in the original hash.
data = {
key1: ["Cop", "dog", "house"],
key2: ["doctor", "cat", "apartment"],
key3: ["Chef", "dog", "house"],
key4: ["Cop", "cat", "apartment"]
}
data.keys.each_with_object(Hash.new([])) { |k, h|
h[data[k][1]] += [k]
}
# => {"dog"=>[:key1, :key3], "cat"=>[:key2, :key4]}
Using group_by but return an array of hashes
The reason the grouped values are Rails objects (your models) is due to the fact that you also start with these objects. You can use the attributes
method to retrieve the attributes of a model instance as a hash.
The following achieves the result you want:
City.all.group_by { |city| city.state.name }
.transform_values { |cities| cities.map(&:attributes) }
If you only want specific attributes, use slice
instead:
City.all.group_by { |city| city.state.name }
.transform_values { |cities| cities.map { |city| city.slice(:id, :name) } }
Note that slice
will return an ActiveSupport::HashWithIndifferentAccess
instance. Which mostly can be used in the same manner as a normal hash, but returns the same value for both hash[:name]
and hash['name']
. If you rather use a normal hash append a to_hash
call after the slice
call.
Related Topics
Disable Devise's :Confirmable On-The-Fly to Batch-Generate Users
Ruby Comparison Operators? == VS. ===
Error Connecting to Redis on 127.0.0.1:6379 (Errno::Econnrefused) - Wercker
Carrierwave Cannot Remove Image
Count Records Created Within the Last 7 Days
Cancan Load_And_Authorize_Resource Triggers Forbidden Attributes
Best Practice for Limiting the Number of Associations Within a Has_Many Relationship
Ruby (With Rails) Convert a String of Time into Seconds
Invoking Knife in a Ruby Class
When Do You Need to Pass Arguments to 'Thread.New'
How to Parse a HTML Table with Nokogiri
How to Replicate Class_Inheritable_Accessor's Behavior in Rails 3.1
Make Text Input Fields and Their Labels Line Up Correctly
Mocking Chain of Methods in Rspec
Why Does Using '-Webkit-Appearance: None' on a Select Option in Osx Make The Text Disappear