Ruby: Как я могу получить хэш с несколькими ключами? - PullRequest
4 голосов
/ 06 апреля 2010

Я беру 5 строк (протокол, IP-адрес источника и порт, IP-адрес и порт назначения) и использую их для хранения некоторых значений в хэше. Проблема заключается в том, что если IP-адреса или порты переключаются между источником и назначением, ключ должен быть одинаковым.

Если бы я делал это в C # / Java / что бы мне ни пришлось создавать новый класс и перезаписывать методы hashcode () / equals (), но это кажется ошибочным из-за того, что я читал об этом и Мне было интересно, будет ли здесь лучшая альтернатива.

Ответы [ 3 ]

4 голосов
/ 06 апреля 2010

Я напрямую копирую абзац из Программирование на Ruby 1.9 :

Хеш-ключи должны отвечать на сообщение hash, возвращая хеш-код, и хеш-код для данного ключа не должен изменяться. Ключи, используемые в хэше, также должны быть сопоставимы с использованием eql?. Если eql? возвращает true для двух ключей, то эти ключи также должны иметь одинаковый хэш-код. Это означает, что некоторые классы (такие как Array и Hash) не могут быть удобно использованы в качестве ключей, поскольку их значения хеш-функции могут изменяться в зависимости от их содержимого.

Таким образом, вы можете сгенерировать ваш хэш как ["#{source_ip} #{source_port}", "#{dest_ip} #{dest_port}", protocol.to_s].sort.join.hash так, чтобы при переключении источника и получателя результат был одинаковым.

Например:

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)

Это выведет один и тот же хеш, даже если между двумя вызовами аргументы находятся в разном порядке. Правильная инкапсуляция этой функциональности в классе оставлена ​​читателю в качестве упражнения.

0 голосов
/ 03 февраля 2015

Вы можете использовать следующий код:

def create_hash(prot, s_ip, s_port, d_ip, d_port, value, x = nil)
  if x
    x[prot] = {s_ip => {s_port => {d_ip => {d_port => value}}}}
  else
    {prot => {s_ip => {s_port => {d_ip => {d_port => value}}}}}
  end
end

# Create a value
h = create_hash('www', '1.2.4.5', '4322', '4.5.6.7', '80', "Some WWW value")

# Add another value
create_hash('https', '1.2.4.5', '4562', '4.5.6.7', '443', "Some HTTPS value", h)

# Retrieve the values
puts h['www']['1.2.4.5']['4322']['4.5.6.7']['80']
puts h['https']['1.2.4.5']['4562']['4.5.6.7']['443']   
0 голосов
/ 06 апреля 2010

Я думаю, это то, что вы имеете в виду ...

irb(main):001:0> traffic = []
=> []
irb(main):002:0> traffic << {:src_ip => "10.0.0.1", :src_port => "9999", :dst_ip => "172.16.1.1", :dst_port => 80, :protocol => "tcp"}
=> [{:protocol=>"tcp", :src_ip=>"10.0.0.1", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}]
irb(main):003:0> traffic << {:src_ip => "10.0.0.2", :src_port => "9999", :dst_ip => "172.16.1.1", :dst_port => 80, :protocol => "tcp"}
=> [{:protocol=>"tcp", :src_ip=>"10.0.0.1", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}, {:protocol=>"tcp", :src_ip=>"10.0.0.2", :src_port=>"9999", :dst_ip=>"172.16.1.1", :dst_port=>80}]

Следующий, несколько связанный вопрос, заключается в том, как хранить IP. Возможно, вы захотите использовать объект IPAddr вместо строки, чтобы упростить сортировку результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...