Не присваивать хэшу значения nil
Существует ли короткая рука или лучшая практика для назначения вещей хэшу, когда они равны нулю в ruby? Например, моя проблема заключается в том, что я использую другой хэш для построения этого, и если что-то в нем равно nil, он присваивает nil этому ключу, а не просто оставляет его в покое. Я понимаю, почему это происходит, поэтому мое решение было:
hash1[:key] = hash2[:key] unless hash2[:key].nil?
Потому что я не могу иметь значение в has, где ключ фактически указывает на ноль. (Я бы предпочел иметь пустой хэш, чем тот, который имеет {: key => nil}, который не может случиться)
Мой вопрос: есть ли лучший способ сделать это? Я не хочу делать delete_if в конце заданий.
7 ответов:
Немного короче, если вы отрицаете утверждение" если только "
hash1[:key] = hash2[:key] if hash2[:key] # same as if ! hash2[:key].nil?
Вы также можете сделать сравнение в операторе&&, как предложено в других ответах Майкла или Марка-Андре
Это действительно зависит от вас, то, что вы чувствуете, является наиболее читаемым для вас. По замыслу, в Ruby всегда есть несколько способов решить проблему.Вы также можете изменить хэш2:
hash1 = hash2.reject{|k,v| v.nil?} hash2.reject!{|k,v| v.nil?} # even shorter, if in-place editing of hash2
Это удалит пары ключ / значение: ключ = > nil из hash2 (на месте, если вы используете отклонение! )
Я не уверен, что это действительно лучше, но
hash2[:key] && hash[:key] = hash2[:key]
Может сработать. Обратите внимание, что это будет вести себя так же для
false
иnil
, Если это не то, что вы хотите!hash2[:key].nil? && hash[:key] = hash2[:key]
Было бы лучше. Все это предполагает, что
:key
будет произвольным значением, которое вы не можете контролировать.
Мне это нравится больше всего, цикл и условное переопределение все в одной строке!
h1 = {:foo => 'foo', :bar => 'bar'} h2 = {:foo => 'oof', :bar => nil} h1.merge!(h2) { |key, old_val, new_val| new_val.nil? ? old_val : new_val } #=> {:foo => 'oof', :bar => 'bar'}
Это заменит каждое значение в h1 на значение h2, где ключи одинаковы и значение h2 не равно нулю.
Я считаю, что лучше всего скопировать значение
nil
в хэш. Если кто-то передает опцию:foo => nil
, это может что-то значить и должно переопределить значение по умолчанию:foo
из42
, например. Это также облегчает выбор опций, которые по умолчанию должны иметь значениеtrue
, хотя в этих случаях следует использоватьfetch
:Существует множество способов копирования значений, включаяopt = hash.fetch(:do_cool_treatment, true) # => will be true if key is not present
nil
илиfalse
.Для одного ключа можно использовать
has_key?
вместо поиска:hash1[:key] = hash2[:key] if hash2.has_key? :key
Для все (или многие) ключи, используйте
merge!
:hash1.merge!(hash2)
Если вы хотите сделать это только для пары ключей
hash2
, вы можете нарезать его:hash1.merge!(hash2.slice(:key, ...))
Как насчет чего-то вроде этого?
hash2.each_pair do |key, value| next if value.nil? hash1[key] = value end
Если вы делаете только одно задание, это может побрить несколько символов:
hash2[:key] && hash1[:key] = hash2[:key]
Мой первый пример можно было бы также побрить немного дальше:
hash2.each_pair{ |k,v| v && hash1[k] = v }
Я думаю, что первое легче всего прочитать / понять. Кроме того, примеры 2 и 3 пропустят все, что дает оценку false (
nil
илиfalse
). Этот последний пример является одной строкой и не пропускает значенияfalse
:hash2.each_pair{ |k,v| v.nil? || hash1[k] = v }
Хорошо, так что если слияние не работает, потому что вы хотите больше контроля:
hash1[:key] = hash2.fetch(:key, hash1[:key])
Это установит ключ hash1 :в качестве hash2, если он не существует. В этом случае он будет использовать значение по умолчанию (2-й аргумент для выборки), которое является ключом hash1