2014-04-02 56 views
0

我有這樣的代碼:使用散列值等的時間間隔

@counter = 719  

@period_hash = { 
    :sunset => 360, 
    :day => 720, 
    :dawn => 1200, 
} 

@period = :nothing 

def init_period 
    periods = @period_hash.keys 
    @period_hash.each_with_index do |(__, number), index| 
    if @counter < number 
     @period = periods[index - 1] 
     break 
    end 
    end 
    if @period == :nothing 
    @period = periods[-1] 
    end 
end 

init_period 
p @period 

我有一個@counter這將有0和1440之間 值然後我有可變內容的散列。內容將始終爲符號=>整數 整數值也將是一個介於0和1440之間的數字,並且所有數字在散列中都是唯一的 。哈希將被排序,所以最低的數字將是第一個,最高的數字 將是最後一個。

然後我有一個方法(init_period),它將返回對應於@counter變量的鍵。 這些是@counter的間隔和返回的符號:

0 .. 359 => :dawn 
360 .. 719 => :sunset 
720 .. 1199 => :day 
1200 .. 1440 => :dawn 

所有的工作,但如果有其他更好的方式做同樣的我想知道。

回答

0

您可以使用以下代碼將散列轉換爲不同的結構。這不是很清楚,因爲您正在使用@period_hash以外的信息(如全局範圍邊界以及必須重用最後一個值的事實)。

hash = @period_hash. 
    keys. 
    unshift(@period_hash.keys.last). # reuse last key from hash 
    zip(        # zip keys with ranges 
    [0, *@period_hash.values, 1440]. # add 0 and 1440 as boundaries 
    each_cons(2)      # convert array to consecutive pairs enum 
).each_with_object({}) {|(key, (from, to)), hash| 
    hash[from...to] = key   # build actual hash 
    } 

在此結構可以調用的代碼,將檢測週期:你跟真的無法讀取的代碼最終

hash.detect {|a,b| a.include?(719) } 

。如果你的月經是不會改變的時候,你可以去非常可讀的代碼:

def init_period(counter) 
    case counter 
    when 0...360  then :dawn 
    when 360...720 then :sunset 
    when 720...1200 then :day 
    when 1200...1440 then :dawn 
    end 
end 

這樣一段邊界不會從外部結構拍攝,但代碼是顯而易見的,明確的。

+0

謝謝,我的第一個解決方案是案例,但後來我意識到,我寫了一個腳本供其他人使用(也有些人沒有編程知識),我想讓它更具動感。我的腳本的用戶可以配置散列並隨意添加儘可能多的項目,只要他們遵守規則即可。向hash中添加一些內容會更容易,例如:night => 1300,然後在代碼中的某處添加一個新的「when」到case語句。 – Eugen

+1

*另一方面,範圍可以在case語句中使用。什麼結構應該高度使用取決於實際使用情況。*(來自samuil的評論,哈哈)。你的答案使用範圍和'case'語句是完全沒有用的,因爲OP明確指出哈希具有「可變內容」。您無法更改在case語句中硬編碼的值。我將把你的話歸還給你:**應該使用哪種結構高度取決於實際使用情況**。你的答案的第一部分是有效的,但是很醜。 – sawa