Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: How can I have a Hash take multiple keys?

Tags:

ruby

hash

I'm taking 5 strings (protocol, source IP and port, destination IP and port) and using them to store some values in a hash. The problem is that if the IPs or ports are switched between source and destination, the key is supposed to be the same.

If I was doing this in C#/Java/whatever I'd have to create a new class and overwrite the hashcode()/equals() methods, but that seems error prone from the little I've read about it and I was wondering if there would be a better alternative here.

like image 397
zxcvbnm Avatar asked Apr 06 '10 01:04

zxcvbnm


1 Answers

I am directly copying a paragraph from Programming Ruby 1.9:

Hash keys must respond to the message hash by returning a hash code, and the hash code for a given key must not change. The keys used in hashes must also be comparable using eql?. If eql? returns true for two keys, then those keys must also have the same hash code. This means that certain classes (such as Array and Hash) can't conveniently be used as keys, because their hash values can change based on their contents.

So you might generate your hash as something like ["#{source_ip} #{source_port}", "#{dest_ip} #{dest_port}", protocol.to_s].sort.join.hash such that the result will be identical when the source and destination are switched.

For example:

source_ip = "1.2.3.4"
source_port = 1234

dest_ip = "5.6.7.8"
dest_port = 5678

protocol = "http"

def make_hash(s_ip, s_port, d_ip, d_port, proto)
    ["#{s_ip} #{s_port}", "#{d_ip} #{d_port}", proto.to_s].sort.join.hash
end

puts make_hash(source_ip, source_port, dest_ip, dest_port, protocol)
puts make_hash(dest_ip, dest_port, source_ip, source_port, protocol)

This will output the same hash even though the arguments are in a different order between the two calls. Correctly encapsulating this functionality into a class is left as an exercise to the reader.

like image 198
Mark Rushakoff Avatar answered Nov 19 '22 01:11

Mark Rushakoff