Что такое элегантный способ Ruby иметь условие 'ноль'? - PullRequest
0 голосов
/ 14 ноября 2018

Есть ли более элегантный способ написания этого кода?

    def create_a_hash_from_a_collection
      my_hash = {}

      collection_of_hashes.each do |key, value|
        my_hash[key] = {} if my_hash[key].nil?
        my_hash[key] = value
      end

      my_hash
    end

Мне кажется, что строка неуклюжа:

my_hash[key] = {} if my_hash[key].nil?

Есть ликраткий способ выразить это?

Ответы [ 4 ]

0 голосов
/ 14 ноября 2018

Поскольку вы в любом случае присваиваете значение, возможно, вы могли бы использовать my_hash[key] = value || {}?

Итак, если value назначить nil, значение этого ключа становится {}.

0 голосов
/ 14 ноября 2018

Вы можете использовать ||= оператор, который делает именно то, что вы хотите

my_hash[key] ||= {} 

Остальная часть моего ответа здесь, потому что я не уверен, что такое «коллекция хэшей», поэтому я думаю, что это будет массив хэшей. Если я не прав, дайте мне знать и не обращайте внимания на остальную часть этого ответа.

Кажется, что остальная часть вашего метода может не делать то, что звучит так, как будто вы пытаетесь это сделать. Рассмотрим:

@collection_of_hashes = [{foo: 'bar'}, {baz: 'qux'}]

def create_a_hash_from_a_collection
   my_hash = {}
   @collection_of_hashes.each do |key, value|
     # this is not actually doing anything here and returns same with or
     # without the following line
     # my_hash[key] ||= {}
     my_hash[key] = value
   end

   my_hash
 end
#=> {{:foo=>"bar"}=>nil, {:baz=>"qux"}=>nil}

Но что вы, вероятно, хотите, это

def create_a_hash_from_a_collection
  my_hash = {}
  @collection_of_hashes.each do |hash|
    hash.keys.each do |k|
      my_hash[k] = hash[k]
    end
  end
  my_hash
end
#=> {:foo=>"bar", :baz=>"qux"}

Но также имейте в виду, если любая из ваших "коллекций хешей", которые мы склонны считать массивом хешей, содержит тот же ключ, который выигрывает? Этот код, это будет последний элемент в значении ключа массива. Какова реальная цель вашего метода?

0 голосов
/ 14 ноября 2018

Если вы хотите иметь новый хэш для каждого ключа в вашем начальном хеше, вам нужно инициализировать его блоком:

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

hash[:foo].object_id == hash[:bar].object_id #=> false

В противном случае, если вы сделаете это, он всегда будет таким жехеш по умолчанию

hash = Hash.new({})
hash[:foo].object_id == hash[:bar].object_id #=> true
0 голосов
/ 14 ноября 2018

Полагаю, вам нужно инициализировать my_hash значением по умолчанию, поэтому вам не нужно проверять, равен он нулю или нет.

Это можно сделать с помощью конструктора Hash.new, сравните:

my_hash = {}
puts my_hash['no_existing_key'] #=> nil

my_hash = Hash.new({})
puts my_hash['no_existing_key'] #=> {}

Затем вы можете уменьшить свой код до:

def create_a_hash_from_a_collection
  my_hash = Hash.new({})

  collection_of_hashes.each do |key, value|
    my_hash[key] = value
  end

  my_hash
end
...