最近在Ruby编码时,当我需要根据方法的某些输入分配不同的变量时,我一直在使用这样的Hash:
variable = { "option1" => [1,2,3], "option2" => [3,2,1]}[input]
我最喜欢这种方法的是可扩展性:输入可以是五个不同的值之一,其中if
语句会有点混乱。
但是这样做我失去了什么?由于哈希需要初始化,因此内存使用量更大?慢点?快?
为了进行比较,等效的if
语句可以是:
variable = Array.new
if input.eql?("option1")
variable = [1,2,3]
else
variable = [3,2,1]
end
(是的,我可以使用?
表示法来表示两个选项,但不是更多,所以我想在比较中显示结构。)
答案 0 :(得分:6)
我还有两个选择:
使用case
case input
when 'option1'
[1, 2, 3]
else
# default here or error message
end
使用元编程:
class Foo
def option1
[1, 2, 3]
end
def option2
[3, 4, 5]
end
end
Foo.new.send(input)
基准测试将帮助我们确定所有解决方案的性能。但是,性能很好,但代码味道,可读性和可重用性也是您需要注意的事项。使用哈希比if else
语句更灵活,但您可能会在某个时候达到hash
实现的限制。
case
更具可读性,但在有很多条件时会非常难看......
元编程很棒,给你很大的灵活性,但在你的情况下可能有点过分。
答案 1 :(得分:3)
我更喜欢哈希方法的一个原因是它将逻辑转移到数据本身。现在,如果添加更多规则,则只需更改数据,而不是代码。您可以从外部源(配置文件,网络等)加载数据。简而言之:灵活性。
如果我们谈论性能,那么这两种方法几乎完全相同。我怀疑你能否发现任何差异(在现实世界的应用程序中)。
答案 2 :(得分:3)
如果您正在使用哈希,请务必定义一次(作为常量)。
一些基准测试(针对运行时):
#!/usr/local/bin/ruby -w
require 'benchmark'
def by_hash1(i)
{ "option1" => [1,2,3], "option2" => [3,2,1] }[i]
end
TheHash = {
"option1" => [1,2,3],
"option2" => [3,2,1],
}
def by_hash2(i)
TheHash[i]
end
def by_case(i)
case i
when 'option1'
[1, 2, 3]
when 'option2'
[3, 2, 1]
end
end
def by_if(i)
if i.equal?('option1')
[1, 2, 3]
else
[3, 2, 1]
end
end
class Foo
def self.option1
[1, 2, 3]
end
def self.option2
[3, 4, 5]
end
end
N = 10_000_000
Inps = %w{ option1 option2 }
Benchmark.bm(10) do | x |
x.report('by hash1') { N.times { by_hash1(Inps.sample) } }
x.report('by hash2') { N.times { by_hash2(Inps.sample) } }
x.report('by case') { N.times { by_case(Inps.sample) } }
x.report('by if') { N.times { by_if(Inps.sample) } }
x.report('meta') { N.times { Foo.send(Inps.sample) } }
end
给出
user system total real
by hash1 11.529000 0.000000 11.529000 ( 11.597000)
by hash2 2.387000 0.000000 2.387000 ( 2.401000)
by case 3.151000 0.000000 3.151000 ( 3.155000)
by if 3.198000 0.000000 3.198000 ( 3.236000)
meta 3.541000 0.000000 3.541000 ( 3.554000)
on ruby 2.0.0p195(2013-05-14)[x64-mingw32]。
请注意,我认为表现通常不太重要。只有遇到性能问题,才应该开始调查。否则,可读性等问题就更为重要。