在 Ruby 中工作时,我经常发现自己在使用带有 a的方法!
或使用普通方法来分配值之间存在冲突。我不确定何时使用什么。例如,我有 2 个哈希(h1 和 h2),我想合并它们并将值存储回哈希 h1,现在我应该使用
h1.merge!(h2)
or
h1 = h1.merge(h2)
吗?
两者有什么区别吗?
在 Ruby 中工作时,我经常发现自己在使用带有 a的方法!
或使用普通方法来分配值之间存在冲突。我不确定何时使用什么。例如,我有 2 个哈希(h1 和 h2),我想合并它们并将值存储回哈希 h1,现在我应该使用
h1.merge!(h2)
or
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)
因此,如果您需要速度,请远离。否则,不要冒险。