!
Ruby で作業しているときに、値の代入としてメソッドを使用するか、通常のメソッドを使用するかで競合することがよくあります。いつ何を使うかわかりません。たとえば、2 つのハッシュ (h1 と h2) があり、それらをマージして値をハッシュ h1 に格納したい場合、or を使用する
必要がありますh1.merge!(h2)
か
h1 = h1.merge(h2)
?
両者に違いはありますか?
!
Ruby で作業しているときに、値の代入としてメソッドを使用するか、通常のメソッドを使用するかで競合することがよくあります。いつ何を使うかわかりません。たとえば、2 つのハッシュ (h1 と h2) があり、それらをマージして値をハッシュ h1 に格納したい場合、or を使用する
必要がありますh1.merge!(h2)
か
h1 = h1.merge(h2)
?
両者に違いはありますか?
ほとんどの場合、 と の間にほとんど違いはありませh1.merge!(h2)
んh1 = h1.merge(h2)
。
ただし、次の点に注意してください。
は古いハッシュを変更するためmerge!
、同じハッシュへの参照を保持するプログラム内の他のオブジェクトに意図せず影響を与える可能性があります。メソッド パラメーターとして受け取ったハッシュを変更することは、通常、呼び出し元が想定していないため、不適切な方法です。
merge!
あなたがそのファンなら、使用は関数型プログラミングではありません。
merge!
特に大きなハッシュの場合、新しいハッシュを作成しないため、を使用する方がおそらく効率的です。
私はmerge
ほとんどの場合使用merge!
し、安全で優れていると判断した場合にのみ使用します.
両者に違いはありますか?
はい、もちろんあります。
受信機自体を変更したい場合は、!
(bang) バージョンを使用する必要があります。Hash#merge
例
h1 = {a: 1}
h2 = {b: 2}
h3 = h1.merge(h2) # => {:a=>1, :b=>2}
h1 # => {:a=>1}
今見てください:
h1 = {a: 1}
h2 = {b: 2}
h1.merge!(h2) # => {:a=>1, :b=>2}
h1 # => {:a=>1, :b=>2}
h1 = h1.merge(h2) は同じ答えを返します
うーん、それは、メソッドh1
を適用した後に新しいハッシュを割り当てているためです。Hash#merge
h1 = {a: 1}
h2 = {b: 2}
h1.object_id # => 69435570
h1 = h1.merge(h2) # => {:a=>1, :b=>2}
h1 # => {:a=>1, :b=>2}
h1.object_id # => 69434820
あなたが言ったように、それらをマージして値をハッシュ h1 に保存したいので、使用するHash#merge!
ことをお勧めします。h1 = h1.merge(h2)
h1.merge!(h2)
h1
Ruby で作業していると、! を使用したメソッドの使用が競合することがよくあります。または通常の方法を使用します。
もっと重要なことを考えるべきなので、ルールを採用してください: bang メソッドは絶対に使用しません。今、自由になり、舞い上がる...
require 'benchmark'
n = 1_000_000
h1 = {a: 1, b: 2}
h2 = {b: 3, c: 4}
Benchmark.bm(20) do |b|
b.report("no-bang-hash-merge") do
n.times { h1 = h1.merge h2 }
end
b.report("bang-hash-merge") do
n.times { h1.merge! h2 }
end
end
--output:--
user system total real
no-bang-hash-merge 2.750000 0.050000 2.800000 ( 2.817345)
bang-hash-merge 0.400000 0.000000 0.400000 ( 0.406870)
.
require 'benchmark'
hash_size = 10_000
#Keys overlap:
key1 = 'a'
key2 = nil
h1 = {}
hash_size.times do |i|
h1[key1] = i
key2 = key1.dup if i == hash_size/2
key1.succ!
end
h2 = {}
hash_size.times do |i|
h2[key2] = i
key2.succ!
end
=begin
#No overlap:
key = 'a'
h1 = {}
hash_size.times do |i|
h1[key] = i
key.succ!
end
h2 = {}
hash_size.times do |i|
h2[key] = i
key.succ!
end
=end
n = 100_000
puts "50% of keys overlap, hash size #{hash_size}:"
Benchmark.bm(20) do |b|
b.report("no-bang-hash-merge") do
n.times { h1 = h1.merge h2 }
end
b.report("bang-hash-merge") do
n.times { h1.merge! h2 }
end
end
--some test runs:---
50% of keys overlap, hash size 10000:
user system total real
no-bang-hash-merge 1500.570000 74.520000 1575.090000 (1695.523240)
bang-hash-merge 255.910000 0.940000 256.850000 (269.957178)
No keys overlap, hash size 10000:
user system total real
no-bang-hash-merge 1906.070000 109.340000 2015.410000 (2151.865636)
bang-hash-merge 162.680000 0.190000 162.870000 (163.369607)
スピードが必要な場合は、強打してください。それ以外の場合は、危険を冒さないでください。