Ruby - 有效地将数据存储在深层嵌套的Hash中?

时间:2011-03-21 08:06:35

标签: ruby data-structures performance hashmap

我正在编写一个脚本,将存储数据信息存储在哈希中,以便以后可以轻松访问。我的代码看起来像这样:

my_hash = {}

connection.query("select * from ...").each_hash do |row|
  date = row['date']
  ip   = row['ip']
  port = row['port']
  resp = row['avg_resp_time'].to_i

  unless my_hash.key?(ip)
    my_hash[ip] = { date => { port => resp } }
  else
    unless my_hash[ip].key?(date)
      my_hash[ip][date] = { port => resp }
    else
      unless my_hash[ip][date].key?(port)
        my_hash[ip][date][port] = resp 
      end
    end
  end
end

这只是一个示例,但实际的哈希有时会嵌套5-6级深度,并且需要很长时间来构建大型结果集。我意识到在构建映射时间/访问时间数据之间存在权衡,但我想知道是否存在一种更有效的方式来存储数据以便在代码中轻松访问,或者是一种制作方法我当前的脚本效率更高 - 这个哈希构建循环是我目前的瓶颈。感谢。

2 个答案:

答案 0 :(得分:4)

惯用的Ruby就是使用Hash构造函数来丢失密钥:

>> data = Hash.new { |hash, key| hash[key] = {} }
>> data[:a][:b] = {:x => 5}
>> data
=> {:a=>{:b=>{:x=>5}}}

[edit]我不确定你在这里需要它,但上面的代码仅适用于一个嵌套级别。对于无限嵌套:

class Hash
  def self.new_recursive 
    self.new { |hash, key| hash[key] = self.new_recursive }
  end
end

data = Hash.new_recursive
....

但是,我倾向于不喜欢非功能性解决方案,因此您可能会看到Enumerable#group_by或SQL级别的某种分组,Enumerable #injection来构建嵌套哈希。只是一些原始的想法,所以你可以玩一点。

答案 1 :(得分:2)

如何将数组指定为键?例如

my_hash[[ip, date, port]] = resp

甚至

my_hash[[ip, date, port, resp]] = true

取决于您的目的。这将减少不必要的嵌套,并提高效率。