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 endNow 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!
1 Comments:
At 6/05/2007 02:22:00 PM, 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