2 level deep grouping in ruby
So I have a array of records and I would like to group by 2 levels
Essentially I would like to group_by{|x| x.field1 }
and then each value in hash to be further grouped in by field2. Effectively leading to a tree that I can开发者_如何学JAVA dump out.
def treemaker(array = [])
tree = ledgers.group_by{|x|x.master_group}
tree.each{|x,z| tree[x] = z.group_by{|y| y.account_group}}
tree
end
I would then render tree in a way that i can be put into a "tree" javascript plugin.
Is there a more efficient way?
Sample Input: An Array of ActiveRecord objects, where the model contains, fields master_group, account_group and name
Class MyModel < ActiveRecord::Base
validates :master_group, :account_group, :name, :presence => true
end
Sample Ouput:
{"master_group1" => {"account_group1" => ["name1","name2",...],
"account_groupx" => ["name3", "name4",...],
....},
"master_group2" => {"account_group2" => ["namex", "namey"]},
...
}
I'm not specifically looking for an "SQL grouping" solution (but that would be nice too). Just a solution using enumerables on a any given list of ruby objects.
@xaxxon sent me thinking in the right way basically with the "default value of hash" path.
I think i can now add a method to my model where i can use all sorts of scopes and tack on tree at the end to get my models in tree mode.
class MyModel < ActiveRecord::Base
validates :master_group, :account_group, :name, :presence => true
def self.tree(field1 = 'master_group', field2 = 'account_group')
tree = Hash.new{|hash,key| hash[key] = Hash.new{|h,k| h[k] = []}}
all.each do |item|
tree[item.send('field1')][item.send('field2')].push(item)
end
tree # bob's your uncle!
end
end
MyModel.recent.tree => Hash of Hash of arrays
set up some fake data
foo=[{:a=>1,:b=>2},{:a=>3,:b=>4}]
set up the output data structure
tree={}
populate the output data structure - this is weird looking because you have to populate the hashes that don't exist when they don't exist, hence the ||={} stuff.
foo.each{|thing| (tree[thing[:a]]||={})[thing[:b]]=thing}
looks good.. :a is your master group and :b is your account_group
pp tree
{1=>{2=>{:a=>1, :b=>2}}, 3=>{4=>{:a=>3, :b=>4}}}
精彩评论