Ruby何时使用方法!vs重新赋值
在使用Ruby时,我经常发现自己在使用方法和Ruby何时使用方法!vs重新赋值,ruby,Ruby,在使用Ruby时,我经常发现自己在使用方法和之间存在冲突或使用普通方法将值赋回。我不知道什么时候用什么。 例如 我有两个散列(h1和h2),我想合并它们并将值存储回散列h1,现在我应该使用吗 h1.merge!(h2) 或 h1=h1.合并(h2) 这两者有什么区别吗 这两者有什么区别吗 是的,当然有 你应该使用(bang)版本,当您要更改接收器本身时 示例 h1 = {a: 1} h2 = {b: 2} h3 = h1.merge(h2) # => {:a=>1, :b=>2
之间存在冲突代码>或使用普通方法将值赋回。我不知道什么时候用什么。
例如
我有两个散列(h1和h2),我想合并它们并将值存储回散列h1,现在我应该使用吗
h1.merge!(h2)
或
h1=h1.合并(h2)
这两者有什么区别吗
这两者有什么区别吗
是的,当然有
你应该使用代码>(bang)版本,当您要更改接收器本身时
示例
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。合并(h2)给出了相同的答案
嗯,这是因为,在应用hash#merge
方法之后,您正在将新哈希分配到h1
:
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,那么我建议使用。因为h1=h1.merge(h2)
与h1.merge相同!(h2)
(将保存新的哈希创建,并将其分配回h1
)。大多数情况下h1.merge之间的差异非常小!(h2)
和h1=h1。合并(h2)
但是,请注意:
自从<代码>合并如果代码>修改旧的散列,则可能会无意中影响程序中包含对该散列的引用的其他对象。修改作为方法参数接收的哈希是一种不好的做法,因为调用方通常不期望它
使用合并
不是函数式编程,如果你喜欢的话
使用合并
可能更有效,因为它不会创建新的散列,特别是对于大型散列
我大部分时间都会使用merge
,而只使用merge代码>如果我确定它是安全和更好的
在使用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)
因此,如果你需要速度,砰的一声离开。否则,不要冒险。h1=h1。合并(h2)给出了相同的答案。在大多数情况下,我宁愿避免副作用(有时用!
表示)。我发现减少副作用(在任何语言中)通常会使代码更容易推理,并有助于避免一些微妙的意外交互。我发现字符串的副作用(gsub!
etc)尤其难以处理,部分原因是许多常见的“现代”语言没有Ruby这样的可变字符串。(当然有很多非!
方法也会产生副作用..而且Ruby无论如何都不会试图做到“纯粹”)+1用于比给定用例更大规模的思考。不要违背其他程序员的期望,这一点很重要。像这样的测试没有多大意义,因为散列的大小和重叠键的数量可能会改变结果。我现在正在运行一些额外的测试,我将发布结果。当然,我正在等待看到这些结果:)
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)