1

最近在 Ruby 中编码时,当我需要根据方法的某些输入以不同方式分配变量时,我一直在使用这样的哈希:

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

(是的,我可以?对两个选项使用符号,但不能用于更多,所以我想展示比较的结构。)

4

3 回答 3

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)

基准将帮助我们确定所有给定解决方案的性能。然而,性能很好,但代码味道、可读性和可重用性也是你需要注意的。使用 Hash 比语句更灵活,但您可能会发现自己在某些时候if else达到了实现的极限。hash

case更具可读性,但在有很多条件时可能会非常难看......

元编程很棒,为您提供了很大的灵活性,但在您的情况下可能有点过头了。

于 2013-07-08T09:39:04.487 回答
3

我更喜欢哈希方法的原因之一是它将逻辑转移到数据本身。现在,如果您添加更多规则,您只需要更改数据,而不是代码。您可以从外部源(配置文件、网络等)加载数据。简而言之:灵活性

如果我们谈论性能,那么这两种方法几乎相同。我怀疑您是否能够检测到任何差异(在现实世界的应用程序中)。

于 2013-07-08T09:37:13.937 回答
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)

在我的红宝石 2.0.0p195 (2013-05-14) [x64-mingw32] 上。

请注意,我认为性能通常是次要的。只有当您遇到性能问题时,您才应该开始调查。否则,诸如可读性之类的事情更重要。

于 2013-07-08T09:50:10.470 回答