Ruby - эффективно хранить данные в глубоко вложенном Hash? - PullRequest
1 голос
/ 21 марта 2011

Я пишу скрипт, в котором хранится информация о БД в хэше, чтобы впоследствии он был доступен для легкого доступа.Мой код выглядит примерно так:

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 ]

4 голосов
/ 21 марта 2011

Идиоматический Ruby для этого - использовать конструктор Hash для отсутствующих ключей:

>> 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_by или какую-то группировку на уровне SQL, Enumerable # inject для создания вложенногохэши.Просто несколько сырых идей, чтобы вы могли немного поиграть.

2 голосов
/ 21 марта 2011

Как насчет назначения массива в качестве ключа? Например

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

или даже

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

в зависимости от вашей цели. Это уменьшит ненужное вложение и увеличит эффективность.

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