Creating a nested hash from a sorted array in Ruby - recursive group_by

I have an array of objects sorted by several properties of these objects. In priority order, these properties are foo , bar and baz . This means that objects are first sorted using foo ; then subsequences having the same foo value are sorted by bar ; and then those with the same foo and bar values ​​sorted by baz .

I would like to turn this into a nested hash that reflects this grouping. I am mainly looking for recursive Enumerable#group_by . The keys are the values foo , bar and baz ; the values ​​will be either sub-hashes or arrays of objects. Here is an example:

 [obj1, obj2, ... objn].group_by_recursive(:foo, :bar, :baz) #=> { foo_val_1 => { bar_val_1 => { baz_val_1 => [ obj1, obj2, obj3 ], baz_val_2 => [ obj4, obj5 ] }, bar_val_2 => { baz_val_1 => [ obj6, obj7 ], baz_val_2 => [ obj8 ] }, }, foo_val_2 => { ... }, ... } 
+6
source share
2 answers

I came up with a pretty good solution. Monkey-patch Enumerable like this:

 module Enumerable def group_by_recursive(*props) groups = group_by(&props.first) if props.count == 1 groups else groups.merge(groups) do |group, elements| elements.group_by_recursive(*props.drop(1)) end end end end 

The properties you pass can be either Procs or Symbols

+10
source

Like Sean, and the lack of error handling ...

 class Array def nested_group_by(*keys) return self if keys.length == 0 groups = group_by(&keys.shift) Hash[groups.map { | k, v | [k, v.nested_group_by(*keys)] }] end end 
+1
source

All Articles