Ruby—高效地将数据存储在深度嵌套的哈希中?

Ruby—高效地将数据存储在深度嵌套的哈希中?,ruby,data-structures,performance,hashmap,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[i

我正在编写一个脚本,它将数据库信息存储在一个散列中,以便以后访问。我的代码如下所示:

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层的深处,并且需要很长时间才能构建一个大型结果集。我意识到在构建映射的时间和访问数据的时间之间有一个折衷,但我想知道是否有一种更有效的方法来存储数据,以便在代码中同样容易地访问,或者有一种方法可以使我当前的脚本更有效一点-这个哈希构建循环是我目前的瓶颈。谢谢。

这方面的惯用Ruby是使用哈希构造函数来处理缺少的键:

>> data = Hash.new { |hash, key| hash[key] = {} }
>> data[:a][:b] = {:x => 5}
>> data
=> {:a=>{:b=>{:x=>5}}}
[编辑]我不确定您是否需要它,但上面的代码仅适用于一个嵌套级别。对于无限嵌套:

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

data = Hash.new_recursive
....

但是,我倾向于不喜欢非函数式解决方案,因此您可能会选择Enumerable#group#U by,或者SQL级别的某种分组,即Enumerable#inject来构建嵌套哈希。只是一些原始的想法,这样你可以玩一点。

这方面的惯用Ruby是使用哈希构造函数来处理缺少的键:

>> data = Hash.new { |hash, key| hash[key] = {} }
>> data[:a][:b] = {:x => 5}
>> data
=> {:a=>{:b=>{:x=>5}}}
[编辑]我不确定您是否需要它,但上面的代码仅适用于一个嵌套级别。对于无限嵌套:

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

data = Hash.new_recursive
....

但是,我倾向于不喜欢非函数式解决方案,因此您可能会选择Enumerable#group#U by,或者SQL级别的某种分组,即Enumerable#inject来构建嵌套哈希。只是一些原始的想法,这样你可以玩一点。

将数组指定为键怎么样?比如说

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

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

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

将数组指定为键怎么样?比如说

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

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

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

只要最大级别是固定的,这种方法是好的,但缺乏通用性。在您的示例中,您不能执行
数据[:a][:b][:x]=5
@sawa。的确如果需要多个级别:类Hash def self.recursive new{| Hash,key | Hash[key]=recursive}end endI see。看起来好多了。为什么不把它添加到你的答案中呢?这种方法是好的,只要最高级别是固定的,但它缺乏通用性。在您的示例中,您不能执行
数据[:a][:b][:x]=5
@sawa。的确如果需要多个级别:类Hash def self.recursive new{| Hash,key | Hash[key]=recursive}end endI see。看起来好多了。为什么不把它加到你的答案里呢?