2011-06-12 19 views
6

Necesito una matriz con los números de los meses en el trimestre actual. Quiero suministrar Date.today y luego obtener, p. Ej. [1,2,3].Obtenga los números del mes para el trimestre actual

¿Cómo puedo hacer eso de la manera más fácil? (No usando switch/case).

+3

¿Por qué estás en contra del uso de una declaración de caso aquí? Sería una manera muy simple de hacer lo que estás preguntando. –

+0

Estoy de acuerdo con Andy Waite, realmente DEBERÍA usar una declaración de cambio para tal problema. Todo lo demás sería solo un desperdicio de tiempo de CPU. – fresskoma

Respuesta

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

Bueno, ya que esta es la solución más rápida y también muy concisa, este será el ganador :-) ¡Gracias por sus sugerencias! – jriff

+0

Publiqué un método superligero de una sola línea a continuación. http://stackoverflow.com/a/18668602/839583 – bob

0

Tener un vistazo a este pequeño fragmento:

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

Solución 1

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

Solución 2

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

[* 1..12] esa es una manera ordenada de escribir (1..12) .to_a, gracias por eso, ¡no lo sabía! –

2

que sugeriría la construcción de un hash indexado por mes como Entonces:

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

entonces cualquier consulta de futuro es sólo

@quarters_by_month[month] 

Desde @ x3ro tiempo de CPU mencionada pensé que sería divertido referencia todas las soluciones propuestas, incluyendo la declaración case el que el PO quiere excluir. Aquí están los resultados:

> 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) 

Aquí está el código:

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

Muy interesante, no pensé demasiado en mi solución, pero tan pronto como respondí con la mía, tuve la sensación de que usar una Hash podría ser una solución más rápida. 'def quarter_month_numbers (date) quarters = {0 => [1,2,3], 1 => [4,5,6], 2 => [7,8,9], 3 => [10 , 11,12]} cuartos [(date.month - 1)/3] end' pero es agradable ver a pesar de que entre las soluciones que compararon el mío es el más rápido :) –

+0

Gracias mucho por su referencia - una forma genial de comparar las diferentes soluciones :-) – jriff

0

Usted puede hacer lo siguiente:

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

se demuestra más adelante en el 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] 

I no sé qué tan rápido es esto en comparación con el otro conocido hods, quizás @Wes amablemente puede comparar de esta manera también.

Una ventaja de este enfoque, creo que es la claridad del código. No es complicado.

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

Para 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]] 

Para 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"} 

gustaría que ayudó;)

Cuestiones relacionadas