Ruby deck flips
posted by pete on April 14th, 2009
I’m constantly reminded of why I love Ruby so damn much. I’m not a CompSci scholar, and I know that Lisp did everything first 30 years ago… I guess it’s all about context, isn’t it?
Luckily, this isn’t Reddit and so I’m hoping I can share one of my favourite operators with you. That’s right, I have favourite operators. They make me feel like I have crazy ninja Skate or Die skills, even though there’s very little mystery.
In Ruby we kick around && and || like nerd footbags, but there are a few operators that you might not have realized, and & is one of them.
& (aka the Intersect)
You can be forgiven if, like me, you initially assume that & is a bitwise AND operator. After all, when applied to a Numeric, that’s exactly what it is. (In brief, 1 & x returns 1 when x is an odd number and 0 if x is even. Good for alternating row colours!)
When applied to two Array objects, it returns the elements that are unique in both:
[1, 2, 3] & [2, 3, 4] # => [2, 3]
How many times have you written inefficient double-loop constructs to compare lists? There’s something deeply satisfying about replacing functions with a single character.
What can you do with this little gem? One of my favourites is a simple function to derive the Tanimoto coefficient. This gives you a Float between 0 and 1 which tells you how similar the contents of two lists are. This is useful for correlating tastes, recommending products, and other predictive applications.
def tanimoto(a, b)
c = a & b
c.size.to_f / (a.size + b.size - c.size)
end
x = %w[apple orange banana kiwi]
y = %w[apple pear orange]
puts tanimoto(x, y) # => 0.4
April 14th, 2009 at 12:50 PM
Funny you’d mention Tanimoto/Jaccard: I’ve put code in the wild that uses it, which of course uses & for array intersection.
Yes, this is a shameless plug for “people you may know”, code for a feature you’re familiar with on facebook or linkedin, all in Ruby: http://github.com/danielharan/people_you_may_know/tree/master
April 14th, 2009 at 10:18 PM
I like using the minus operator on Arrays:
[1,2,3] - [2,3,4] # => [1]Useful for situations where you need to determine stragglers, like a list of friends who haven’t yet RSVPed to an event.
your_friends_list - your_birthday_party_attendees # => not_really_your_friendsApril 15th, 2009 at 01:44 PM
1 & anything else most certainly will not always return 0.
April 15th, 2009 at 06:28 PM
Nice catch, Jamie!
I wrote one thing and changed my example. This should learn me not to blog at 3am.
April 30th, 2009 at 09:27 PM
You know, I’m reading Programming Collective Intelligence in which one of the early chapters talks about recommendation systems and the Tanimoto coefficient.
I can’t recall the code exactly, but it was hell of a lot longer than that when he set about comparing dictionaries in Python.
Thanks, Pete.
June 4th, 2009 at 07:02 AM
When you wrote “When applied to two Array objects, it returns the elements that are unique in both” with reference to the AND operator, I think you meant “common to”, not “unique in”. I would interpret “unique” as meaning “no duplicates” or “no repetitions”, which is NOT what you were trying to convey here, in my opinion.
Notwithstanding that, I have recently discovered your “blog” and found it utterly fascinating. Your article titled “Open Says Me” was eye-openingly, jaw-droppingly innovative. I’m not a Ruby guy (although I know Ruby, I don’t have the freedom to use it as much as I would like to), but I’ll still look forward to using the pattern you have described in that article on one of my projects.
Regards, Swaroop Rao