开发者

ruby number to human-readable string conversion

I need to have a list with id's for each list item being #one, #two etc. Is this the most efficient way or am I missing an in built ruby function here?

-num_array = ["one", "two", "three", "four", "five", "six", "seven"]
-navigation[:primary_level].each_with_index do |primar开发者_StackOverflowy_item, idx|
   %li{ :id => "#{num_array[idx]}"}


The humanize gem converts digits into words.


Outside of using the humanize gem, using a hash would be way easier than the array stuff:

lookup = {"one" => 1, "two" => 2, "three" => 3, etc...}
text = "two"
num = lookup[text]


I'm sure this goes well beyond what you need, but there's code to do that at Rosetta Code


Here's my attempt at a solution in Ruby. It is likely suboptimal and has not been checked for correctness.

<<documentation

Converting Numbers to Human Readable Pretty Print Strings

General Description
===================

- Divide the number into groups of three
    - e.g. turn 87012940 -> 87,012,940
- Parse each individual group
    - e.g. 940 -> "nine hundred forty"
    - Only parse the rightmost two numbers
       - 0 -> 12: special cases; use hardcoded switch statements
            - e.g. "one, two, three ... ten, eleven, twelve"
       - 13 -> 19: same hardcoded switch statement + a "-teen" prefix
            - e.g. "thirteen, fourteen, fifteen ... nineteen"
       - 20 -> 99:
            - Parse left digit and return according to the following rule:
                - "twenty, thirty, forty, fifty, sixty ... ninety"
            - Return the simple name of the right digit:
               - "one, two, nine"
                - special case: zero -> ""
      - This is because the hundredth's place follows a simple prefix rule
          - e.g. one-hundred, two-hundred, three-hundred ... nine-hundred
          - special case: zero -> " "
- Add place modifiers according to each group's placement
      - e.g. the middle '012' -> "twelve thousand"
- Concatenate all and return as solution


Algorithm (slightly modified)
=============================

Modifications
-------------

- No need to divide number into groups of three; simply parse right-to-left one at a time
  - When finished processing one group, insert the result leftmost into our final solution string

documentation


def convert(num)
  return 'zero' if (num == 0)

  answer = ''

  places = ['',
               'thousand ',
               'million ',
               'billion ',
               'trillion ',
               'quadrillion ',
               'quintillion ']
  place = 0

  loop do
    break if num == 0

    # Get the rightmost group of three
    first_three_digits = num % 1000

    # Truncate the original number by those three digits
    num /= 1000

    answer.insert(0, convert_group_of_three(first_three_digits) + places[place])
    place += 1
  end

  answer.strip!
end

def convert_group_of_three(num)
  str = ''

  # Zero returns an empty string
  special_cases = ['', 'one ', 'two ', 'three ', 'four ', 'five ', 'six ', 'seven ', 'eight ', 'nine ', 'ten ',
                   'eleven ', 'twelve ', 'thirteen ', 'fourteen ', 'fifteen ', 'sixteen ', 'seventeen ', 'eighteen ', 'nineteen ']
  return special_cases[num % 100] if (0 .. special_cases.length - 1).include? (num % 100)

  # If not in special cases, num must be at least a two digit number
  # Pull the first digit
  first_digit = num % 10
  num /= 10
  str.insert(0, special_cases[first_digit])

  # Pull the second digit
  second_digit = num % 10
  num /= 10

  second_digit_str = ''
  case second_digit
    when 2
      second_digit_str = 'twenty '
    when 3
      second_digit_str = 'thirty '
    when 4
      second_digit_str = 'forty '
    when 5
      second_digit_str = 'fifty '
    when 6
      second_digit_str = 'sixty '
    when 7
      second_digit_str = 'seventy '
    when 8
      second_digit_str = 'eighty '
    when 9
      second_digit_str = 'ninety '
  end
  str.insert(0, second_digit_str)

  # If there is a third digit
  if num > 0
    third_digit = num % 10
    str.insert(0, special_cases[third_digit] + 'hundred ')
  end

  str
end

p convert(2389475623984756)

Output:

"two quadrillion three hundred eighty nine trillion four hundred seventy five billion six hundred twenty three million nine hundred eighty four thousand seven hundred fifty six"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜