2011-06-12 39 views
6

我需要一個數組,其中包含當季的月份數字。我想提供Date.today,然後得到例如。 [1,2,3]獲取當前季度的月份數字

我該如何以最簡單的方式做到這一點? (不是通過使用switch/case)。

+3

爲什麼你反對使用這裏case語句?這將是一個非常簡單的方法來做你的問題。 – 2011-06-12 13:30:16

+0

我同意Andy Waite,你真的應該對這樣的問題使用switch語句。其他一切只會浪費CPU時間。 – fresskoma 2011-06-12 14:02:04

回答

4
def quarter_month_numbers(date) 
    quarters = [[1,2,3], [4,5,6], [7,8,9], [10,11,12]] 
    quarters[(date.month - 1)/3] 
end 
+1

好吧 - 因爲這是最快的解決方案,也非常簡潔,這將是勝利者:-)感謝您的建議! – jriff 2011-06-15 11:52:26

+0

我在下面發佈了一個超級簡單的單線程方法。 http://stackoverflow.com/a/18668602/839583 – bob 2013-09-10 19:15:47

0

看一看這個小片段:

months = (1..12).to_a 
result = months.map do |m| 
    quarter = (m.to_f/3).ceil 
    ((quarter-1)*3+1..quarter*3).to_a 
end 

puts result.inspect 
1

解決方案1 ​​

(((Date.today.month - 1)/3) * 3).instance_eval{|i| [i+1, i+2, i+3]} 

解決方案2

[*1..12][((Date.today.month - 1)/3) * 3, 3] 
+1

[* 1..12]這是一個很好的寫法(1..12).to_a,謝謝你,不知道! – 2011-06-13 13:30:30

2

我建議建立按月像索引的散列所以:

@quarters_by_month = Hash[(1..12).map {|v| i=((v-1)/3)*3; [v,[i+1, i+2, i+3]]}] 

那麼任何將來查找只是

@quarters_by_month[month] 

由於@ x3ro提到的CPU時間,我認爲這將是有趣的基準所有建議的解決方案,包括case聲明該OP要排除的。下面是結果:

> ruby jeebus.rb 
        user  system  total  real 
case_statement: 0.470000 0.000000 0.470000 ( 0.469372) 
quarter_month: 0.420000 0.000000 0.420000 ( 0.420217) 
solution1:  0.740000 0.000000 0.740000 ( 0.733669) 
solution2:  1.630000 0.010000 1.640000 ( 1.634004) 
defined_hash: 0.470000 0.000000 0.470000 ( 0.469814) 

下面是代碼:

def case_statement(month) 
    case month 
    when 1,2,3 
    [1,2,3] 
    when 4,5,6 
    [4,5,6] 
    when 7,8,9 
    [7,8,9] 
    when 10,11,12 
    [10,11,12] 
    else 
    raise ArgumentError 
    end 
end 

def defined_hash(month) 
    @quarters_by_month[month] 
end 

def solution1(month) 
    (((month - 1)/3) * 3).instance_eval{|i| [i+1, i+2, i+3]} 
end 

def solution2(month) 
    [*1..12][((month - 1)/3) * 3, 3] 
end 

def quarter_month_numbers(month) 
    @quarters[(month - 1)/3] 
end 


require 'benchmark' 

n = 1e6 

Benchmark.bm(15) do |x| 
    x.report('case_statement:') do 
    for i in 1..n do 
     case_statement(rand(11) + 1) 
    end 
    end 

    x.report('quarter_month:') do 
    @quarters = [[1,2,3], [4,5,6], [7,8,9], [10,11,12]] 

    for i in 1..n do 
     quarter_month_numbers(rand(11) + 1) 
    end 
    end 

    x.report('solution1:') do 
    for i in 1..n do 
     solution1(rand(11) + 1) 
    end 
    end 

    x.report('solution2:') do 
    for i in 1..n do 
     solution2(rand(11) + 1) 
    end 
    end 

    x.report('defined_hash:') do 
    @quarters_by_month = Hash[(1..12).map {|v| i=((v-1)/3)*3; [v,[i+1, i+2, i+3]]}] 

    for i in 1..n do 
     defined_hash(rand(11) + 1) 
    end 
    end 
end 
+0

非常有趣,我沒有想太多的解決方案,但一旦我回答了我的問題,我有一種感覺,使用哈希可能只是一個更快的解決方案。 'def quarter_month_numbers(date) quarters = {0 => [1,2,3],1 => [4,5,6],2 => [7,8,9],3 => [10 ,11,12]} 宿舍[(date.month-1)/ 3] end' 但很高興看到雖然在你比較我的解決方案之中,我是最快的:) – 2011-06-13 13:33:23

+0

非常感謝你的基準測試 - 非常酷的方式來比較不同的解決方案:-) – jriff 2011-06-15 11:54:07

0

你可以做到以下幾點:

m = date.beginning_of_quarter.month 
[m, m+1, m+2] 

在IRB以下證明:

>> date=Date.parse "27-02-2011" 
=> Sun, 27 Feb 2011 
>> m = date.beginning_of_quarter.month 
=> 1 
>> [m, m+1, m+2] 
=> [1, 2, 3] 

我不知道這與其他會面相比有多快或許@Wes也可以以這種方式進行基準測試。

我認爲這種方法的一個優點是代碼的清晰度。這並不複雜。

4
def quarter(date) 
    1 + ((date.month-1)/3).to_i 
end 
0

對於Array

month = Date.today.month # 6 
quarters = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] 
quarters.select { |quarter| quarter.include?(month) } 
=> [[4, 5, 6]] 

對於Hash

month = Date.today.month # 6 
quarters = { 
    [1, 2, 3] => 'First quarter', 
    [4, 5, 6] => 'Second quarter', 
    [7, 8, 9] => 'Third quarter', 
    [10, 11, 12] => 'Fourth quarter', 
} 
quarters.select { |quarter| quarter.include?(month) } 
=> {[4, 5, 6]=>"Second quarter"} 

希望它幫助;)

相關問題