Perfomance improvement

Hi.

What do you think about these changes:

#current_behaviour
def ordinal(number  )
abs_number = number.to_i.abs
if (11..13).include?(abs_number % 100    )
"th"
  else
    case abs_number % 10
      when 1; "st"
      when 2; "nd"
      when 3; "rd"
      else    "th"
    end
  end
end

#new behaviour
def ordinal2(number  )
tmp = number.to_i.abs % 100

  if 11 <= tmp && tmp <= 13
    "th"  .freeze
else
    case tmp % 10
      when 1; "st"      .freeze
when 2; "nd"      .freeze
when 3; "rd"      .freeze
else    "th"    .freeze
end
  end
end

Benchmark.ips do |x  |
x.report('before') { ordinal(1523  ) }
x.report('after') { ordinal2(1523  ) }
x.compare!
end
              Calculating -------------------------------------
before 111.577k i/100ms
after 143.646k i/100ms

:+1: PR welcome.

It can goes further if using a hash instead of a case statement:

#other new behavior

ORDS = { 1 => 'st', 2 => 'nd', 3 => 'rd' } ORDS.default = 'th' ORDS.freeze def ordinal3(number)
tmp = number.to_i.abs % 100
if 11 <= tmp && tmp <= 13
‘th’.freeze
else
ORDS[tmp % 10].freeze
end
end

``

require ‘benchmark/ips’
#current_behaviour
def ordinal(number)
abs_number = number.to_i.abs

if (11…13).include?(abs_number % 100)
“th”
else
case abs_number % 10
when 1; “st”
when 2; “nd”
when 3; “rd”
else “th”
end
end
end

#new behaviour
def ordinal2(number)
tmp = number.to_i.abs % 100

if 11 <= tmp && tmp <= 13
“th”.freeze
else
case tmp % 10
when 1; “st”.freeze
when 2; “nd”.freeze
when 3; “rd”.freeze
else “th”.freeze
end
end
end

ORDS = { 1 => ‘st’, 2 => ‘nd’, 3 => ‘rd’ }
ORDS.default = ‘th’
ORDS.freeze

#other new behavior
def ordinal3(number)
tmp = number.to_i.abs % 100
if 11 <= tmp && tmp <= 13
‘th’.freeze
else
ORDS[tmp % 10].freeze
end
end

Benchmark.ips do |x|
x.report(‘before’) { ordinal(1523) }
x.report(‘after 1’) { ordinal2(1523) }
x.report(‘after 2’) { ordinal3(1523) }

x.compare!
end

``