Не присваивать хэшу значения 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 presentnilили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