2013-07-08 86 views
1

最近在Ruby中編碼的時候,當我需要分配不同,這取決於一些輸入的方法的變化,我一直在使用這樣的哈希過:變量賦值使用哈希VS if語句

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

'option1'和'option2'的值是否有任何關係?如果是這樣,也許你會想使用'sort()'。 – taiansu

+0

@TaianSu在這個例子中,但我沒有使用它。但謝謝你的提示。我會記住它,如果有未來 –

回答

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 

在我的紅寶石2.0.0p195給

    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) 

(2013年5月14日)[64-的mingw32]。

請注意,我認爲表現通常不太重要。只有遇到性能問題,您才應該開始調查。否則,可讀性等事情更重要。

+0

看看它與if語句結構的比較會很有趣。 –

+0

哈希查找是O(1),因此如果樹(O)不會超過O(n),那就不太可能。 –

+0

@ChrisHeald:但只有兩個選項,它也是O(2)== O(1);-) –

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) 

基準測試將幫助我們確定給出的所有解決方案的性能。但是,性能很好,但是代碼的氣味,可讀性和可重用性也是您需要注意的事情。使用散列比if else聲明更靈活,但您可能會發現自己在某個時刻達到了hash實施的限制。

case可讀性更強,但有很多的條件時,可以說是相當難看......

元編程是偉大的,給你很多的靈活性,但可能會在你的情況是矯枉過正。

+0

你會如何建議基準?會對看到結果感興趣,因此可能需要一些時間才能完成。 –

+0

您需要使用ruby基準測試模塊http://www.ruby-doc.org/stdlib-1.9.3/libdoc/benchmark/rdoc/Benchmark.html來運行包含千元素的不同實現。如果有人還沒有提交一個,我可以在當天試試它:) –