【问题标题】:Ruby - efficiently storing data in deeply nested Hash?Ruby - 有效地将数据存储在深度嵌套的哈希中?
【发布时间】:2011-07-19 12:14:28
【问题描述】:

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

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-structures performance hashmap


    【解决方案1】:

    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#inject 来构建嵌套散列。只是一些原始的想法,所以你可以玩一下。

    【讨论】:

    • 这种方法只要最高级别是固定的就好了,但是缺乏通用性。在您的示例中,您不能执行 data[:a][:b][:x] = 5.
    • @sawa。确实。如果需要不止一层:class Hash def self.recursive new { |hash, key| hash[key] = recursive } end end
    • 我明白了。这样看起来更好。为什么不将其添加到您的答案中?
    【解决方案2】:

    如何将数组分配为键?例如

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

    甚至

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

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

    【讨论】:

      猜你喜欢
      • 2016-10-31
      • 1970-01-01
      • 1970-01-01
      • 2021-04-28
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      相关资源
      最近更新 更多