开发者

Ruby - efficiently storing data in deeply nested Hash?

I'm writing a script the stores db info in a hash to be later available for easy access. My code looks something like this:

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

This is just a sample, but the actual hash is nested sometimes 5-6 levels deep, and takes a long time to build for a large result set. I realize there's a tradeo开发者_StackOverflow中文版ff here between time-to-build-map / time-to-access-data, but I was wondering if there's a more efficient way to store data to be just as easily accessed in code, or a way to make my current script a bit more efficient - this hash building loop is my bottleneck at the moment. thanks.


The idiomatic Ruby for this is to use the Hash contructor for missing keys:

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

[edit] I am not sure you need it here, but the above code works only for one nested level. For infinite nesting:

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

data = Hash.new_recursive
....

However, I tend to dislike non-functional solutions, so you may look Enumerable#group_by, or some kind of grouping in the SQL level, of Enumerable#inject to build the nested hashes. Just some raw ideas so you can play a bit.


What about assigning an array as a key? For example

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

or even

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

depending on your purpose. This will reduce unnecessary nesting, and increase efficiency.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜