ルビーでゼロのときにハッシュに物事を割り当てるための速記またはベストプラクティスはありますか?たとえば、私の問題は、これを構築するために別のハッシュを使用していて、その中の何かがnilの場合、それをそのままにするのではなく、そのキーにnilを割り当てることです。これが発生する理由を理解しているので、私の解決策は次のとおりです。
hash1[:key] = hash2[:key] unless hash2[:key].nil?
キーが実際にnilを指しているhasに値を設定できないためです。 ({:key => nil}を持つハッシュよりも、空のハッシュが必要です。これは発生しません)
私の質問は、これを行うためのより良い方法はありますか?割り当ての最後にdelete_ifを実行したくありません。
「unless」ステートメントを否定すると、少し短くなります
hash1[:key] = hash2[:key] if hash2[:key] # same as if ! hash2[:key].nil?
michaelまたはMarc-Andreによる他の回答で提案されているように、&&ステートメントで比較を行うこともできます。
それは本当にあなた次第です、あなたが感じるものはあなたにとって最も読みやすいです。設計上、問題を解決する方法は常にRuby)にあります。
Hash2を変更することもできます:
hash1 = hash2.reject{|k,v| v.nil?}
hash2.reject!{|k,v| v.nil?} # even shorter, if in-place editing of hash2
これにより、hash2からキーと値のペア:key => nilが削除されます(rejectを使用する場合はその場で!)
私はこれが一番好きで、ループと条件付きオーバーライドをすべて1行で実行します!
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の値がnilではないh2の値に置き換えられます。
このようなものはどうですか?
hash2.each_pair do |key, value|
next if value.nil?
hash1[key] = value
end
割り当てを1つだけ行う場合、これにより数文字が削減される可能性があります。
hash2[:key] && hash1[:key] = hash2[:key]
私の最初の例は、もう少し削ることもできます。
hash2.each_pair{ |k,v| v && hash1[k] = v }
最初のものが最も読みやすく、理解しやすいと思います。また、例2と例3は、falseと評価されるもの(nil
またはfalse
)をスキップします。この最後の例は1行で、false
値をスキップしません。
hash2.each_pair{ |k,v| v.nil? || hash1[k] = v }
それが本当に良いかどうかはわかりませんが
hash2[:key] && hash[:key] = hash2[:key]
動作する可能性があります。これがfalse
とnil
で同じように動作することに注意してください。
!hash2[:key].nil? && hash[:key] = hash2[:key]
の方がいい。このすべては、:key
は、制御できない任意の値になります。
ベストプラクティスは、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, ...))
OK、それで、より多くの制御が必要なためにマージが機能しない場合:
hash1[:key] = hash2.fetch(:key, hash1[:key])
これにより、hash1の:keyが存在しない場合を除き、hash2に設定されます。その場合、hash1のキーであるデフォルト値(フェッチする2番目の引数)が使用されます
これをイニシャライザーに追加しますhash.rb
class Hash
def set_safe(key,val)
if val && key
self[key] = val
end
end
end
使用する
hash = {}
hash.set_safe 'key', value_or_nil