Ruby Group Hashes by Value of Key

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



Leave a reply



Submit