Ruby, iOS, and Other Development

A place to share useful code snippets, ideas, and techniques

All code in posted articles shall be considered public domain unless otherwise noted.
Comments remain the property of their authors.

2007-02-14

Have you seen that key?

This is tiny, but oh, so cool. From time to time I find myself needing a way of checking whether I've seen something. Consider, for example, uniq_by. Here's the implementation of Enumerable#uniq_by I gave previously:

module Enumerable
  def uniq_by
    seen = {}
    select { |v|
      key = yield(v)
      (seen[key]) ? nil : (seen[key] = true)
    }
  end
end
Now we make the "seen" hash a bit smarter:
module Enumerable
  def uniq_by
    seen = Hash.new { |h,k| h[k] = true; false }
    select { |v| !seen[yield(v)] }
  end
end

...and isn't that more concise? It just feels better. Yes, I could swap the true and false in the hash block so I don't need the negation in the #select block, but that has weird semantics. It probably would make more sense to use #reject to avoid the negation, especially since that doesn't force it to return an array:

module Enumerable
  def uniq_by
    seen = Hash.new { |h,k| h[k] = true; false }
    reject { |v| seen[yield(v)] }
  end
end

Enjoy!

Labels: ,

1 Comments:

  • At 6/05/2007 02:22:00 PM, Anonymous Anonymous said…

    Thanks a million for this snippet -- I found that I needed to winnow an array of objects by an associated attribute (in Rails) and your bit of code was just the trick!

     

Post a Comment

<< Home