Подтвердить что ты не робот

Один вкладыш вложенного хеша в Ruby? (Я родом из Perl)

Я человек Perl, и я сделал хеши как это некоторое время:

my %date;

#Assume the scalars are called with 'my' earlier

$date{$month}{$day}{$hours}{$min}{$sec}++

Теперь я изучаю Ruby, и до сих пор я нашел, что использование этого дерева - способ сделать много ключей и значение. Есть ли способ использовать простой формат, который я использую с Perl, используя одну строку?

 @date = {                                                                                                                                                                      
        month => {                                                                                                                                                                 
          day => {                                                                                                                                                                 
           hours => {                                                                                                                                                              
              min => {                                                                                                                                                             
                sec => 1                                                                                                                                                           
              }                                                                                                                                                                    
            }                                                                                                                                                                      
          }                                                                                                                                                                        
        }                                                                                                                                                                                                                                                                                                                                                     
      }                   
4b9b3361

Ответ 1

К сожалению, существует простой, практичный способ. Рубиновый эквивалент был бы уродливым, уродливым зверем вроде:

((((@date[month] ||= {})[day] ||= {})[hours] ||= {})[min] ||= {})[sec] = 1

Существует способ назначить значения по умолчанию для отсутствующих ключей в хэшах:

@date = Hash.new { |hash, key| hash[key] = {} }

# @date[:month] is set to a new, empty hash because the key is missing.
@date[:month][:day] = 1

К сожалению, это не работает рекурсивно.

... если вы не создадите его самостоятельно; Ура для Руби!

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

@date = Hash.recursive
@date[month][day][hours][min][sec] = 1
# @date now equals {month=>{day=>{hours=>{min=>{sec=>1}}}}}

Имейте в виду, что все неустановленные значения теперь {}, а не nil.

Ответ 2

Вот несколько вариантов, похожих на ответ, заданный @molf, но без патча обезьяны.

Использование метода factory:

  def hash_tree
    Hash.new do |hash, key|
      hash[key] = hash_tree
    end
  end

  @date = hash_tree
  @date[month][day][hours][min][sec] = 1

С пользовательским классом:

  class HashTree < Hash
    def initialize
      super do |hash, key|
        hash[key] = HashTree.new
      end
    end
  end

  @date = HashTree.new
  @date[month][day][hours][min][sec] = 1

Ответ 3

->f{f[f]}[->f{Hash.new{|h,k|h[k]=f[f]}}]

Очевидно.

Ответ 4

По сравнению с приведенным выше лямбда-выражением это проще, а также в одной строке:

Hash.new {|h,k| h[k] = Hash.new(&h.default_proc) }

Ответ 5

Использование символов, казалось, сработало:

ree-1.8.7-2009.10 > @date = {:month =>{:day => {:hours => {:min => {:sec => 1 } } } } }
 => {:month=>{:day=>{:hours=>{:min=>{:sec=>1}}}}} 

Затем я могу получить val так:

ree-1.8.7-2009.10 > @date[:month][:day]
 => {:hours=>{:min=>{:sec=>1}}}

Ответ 6

Не похоже, что Ruby может начать автовизацию с самого начала, но вы можете легко добавить в эту функциональность. Поиск "рубиновой автовивитации" в Google дает:

http://t-a-w.blogspot.com/2006/07/autovivification-in-ruby.html

Что содержит достойный пример создания хэша, который будет работать так, как вы ищите.

автообнаружение (фасет) рубинового хеша может также быть полезным.

Ответ 7

Вы можете использовать Facets gem Hash.autonew для выполнения той же функции, что и функция recursive, указанная в ответе Molf.

Ответ 8

require 'xkeys'
date = {}.extend XKeys::Hash

date[month, day, hours, min, sec, :else => 0] += 1