开发者

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}}}

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜