From: Robert Klemme Date: 2007-08-09T20:42:38+09:00 Subject: Re: Collect objects from an array based on one unique parame 2007/8/9, Milo Thurston : > Robert Klemme wrote: > > selection = things.select {|x| x.name = "foo"} > > That is closer, but still not quite it. > A slight change of my previously posted code may make it clearer. In > this case I start with an array of "Thing" objects called "things", and > would like an array called "uniquely_named_things" containing Things > where the name is unique. > > > check = Hash.new > uniquely_named_things = Array.new > things.each do |s| > if check[s.name].nil? > uniquely_named_things << s > end > check[s.name] = 1 > end Your code seems to implement something different from your wording. Your wording says "keep only things whose name is not used by another thing". Your code does "keep one thing per unique name". > Basically, I wonder if anything that does the same as this has already > been included in Ruby. There are numerous ways to achieve that. As I am a big fan of #inject, this is probably my first choice: # 1. keep only one thing per name selection = things.inject({}) {|h,th| h[th.name] ||= th; h}.values # 2. keep things whose name is unique selection = things. inject(Hash.new {|h,k| h[k]=[]}) {|h,th| h[th.name] << th; h}. select {|k,v| v.size == 1}. map {|k,v| v} # 2. alternative impl. selection.things. inject({}) do |h,th| h[th.name] = h.has_key? th.name ? nil : th h end.values.compact If I am not mistaken David's code implements the second solution similar to my alternative implementation. Kind regards robert