From: William James Date: 2006-12-20T06:55:10+09:00 Subject: Re: ruby puzzle: Group candies by unique record fields Brad Phelan wrote: > Woga Swoga wrote: > > I have an list of objects (Candy) and each object has two fields > > (Candy.color, Candy.taste). I would like to display the candies but > > group them based on the fields (display a header for each group). The > > problem is I don't know how many colors or tastes are in any particular > > list of candies. > > > > This is what I have for input: > > > > * Candy <-- hash list already pre-sorted by "group" > > * group <-- variable contains either "color" or "taste" > > > > Can anyone come up with a ruby code snipet that will use the "group" > > variable to extract out the group labels (unique values of the color or > > tate field), and then dump out the Candy list by group. > > > > Really appreciate your help! > > > > require 'yaml' > > @candies = [ > { :name => 'a', :color => "blue", :taste => "good" }, > { :name => 'b',:color => "blue", :taste => "yuck" }, > { :name => 'c',:color => "red", :taste => "ok" }, > { :name => 'd',:color => "blue", :taste => "yuck" }, > { :name => 'e',:color => "green", :taste => "good" }, > { :name => 'f',:color => "green", :taste => "yuck" } > ] > > def print_candies_by(group) > groups={} > @candies.each do |candy| > key = candy[group] > groups[key] = [] unless groups[key] > groups[key] << candy > end > > puts "##########'" > puts YAML.dump groups > puts "##########'" > end > > > print_candies_by :taste > print_candies_by :color > > ---------------- > ##########' > --- > good: > - :taste: good > :name: a > :color: blue > - :taste: good > :name: e > :color: green > yuck: > - :taste: yuck > :name: b > :color: blue > - :taste: yuck > :name: d > :color: blue > - :taste: yuck > :name: f > :color: green > ok: > - :taste: ok > :name: c > :color: red > ##########' > ##########' > --- > green: > - :taste: good > :name: e > :color: green > - :taste: yuck > :name: f > :color: green > blue: > - :taste: good > :name: a > :color: blue > - :taste: yuck > :name: b > :color: blue > - :taste: yuck > :name: d > :color: blue > red: > - :taste: ok > :name: c > :color: red > ##########' $candies = [ { :name => 'a', :color => "blue", :taste => "good" }, { :name => 'b',:color => "blue", :taste => "yuck" }, { :name => 'c',:color => "red", :taste => "ok" }, { :name => 'd',:color => "blue", :taste => "yuck" }, { :name => 'e',:color => "green", :taste => "good" }, { :name => 'f',:color => "green", :taste => "yuck" } ] def print_candies_by property values = $candies.inject([]){|ary,hash| ary << hash[property] }.uniq values.sort.each{|val| puts val $candies.select{|h| h[property] == val}.each{|h| puts " " + h.to_a.reject{|k,v| k == property }. map{|k,v| "#{k}: #{v}"}.join( "; " ) } } end print_candies_by :color --- output ----- blue name: a; taste: good name: b; taste: yuck name: d; taste: yuck green name: e; taste: good name: f; taste: yuck red name: c; taste: ok