Ruby group hashes by value of key

本秂侑毒 提交于 2019-12-03 22:59:47
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.

Something like this perhaps?

mangled = a.group_by { |h| h['type'].to_i }.each_with_object({ }) do |(k,v), memo|
    tk = ('type_' + k.to_s).to_sym
    memo[tk] = v.map { |h| h = h.dup; h.delete('type'); h }
end

Or if you don't care about preserving the original data:

mangled = a.group_by { |h| h['type'].to_i }.each_with_object({ }) do |(k,v), memo|
    tk = ('type_' + k.to_s).to_sym
    memo[tk] = v.map { |h| h.delete('type'); h } # Drop the h.dup in here
end
by_type = {}

a.each do |h|
   type = h.delete("type").to_s
   # type = ("type_" + type ).to_sym

   by_type[ type ] ||= []
   by_type[ type ] << h      # note: h is modified, without "type" key

end

Note: slightly different hash keys here, i used the type values directly as the key

if you have to have the hash-keys as in your example, you can add the line that is commented out.


P.S.: I just saw Tapio's solution -- it is very nice and short! Note that it only works with Ruby >= 1.9

group_by collects an enumerable into sets, grouped by the result of a block. You are not constrained to simply get the key's value in this block, so if you would like to omit the 'type' in those sets you can do it, like in:

array.group_by {|x| "type_#{x.delete('type').to_i}".to_sym}

This will result exactly into what you asked.

Advanced: This goes a little out of scope of the question, but if you want to preserve the original array, you must duplicate every object inside it. This will do the trick:

array.map(&:dup).group_by {|x| "type_#{x.delete('type').to_i}".to_sym}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!