Skip to content

Instantly share code, notes, and snippets.

@dmitryzuev
Created January 26, 2016 18:55
Show Gist options
  • Save dmitryzuev/7d842cddc3127c5941af to your computer and use it in GitHub Desktop.
Save dmitryzuev/7d842cddc3127c5941af to your computer and use it in GitHub Desktop.
Convert human readable number to float in Ruby
# Convert human entered string into number
class StringDecoder
# Hash with powers of 10 by names
POWERS = {
'trillion' => 10**12,
'trillions' => 10**12,
'billion' => 10**9,
'billions' => 10**9,
'million' => 10**6,
'millions' => 10**6,
'thousand' => 10**3,
'thousands' => 10**3,
}.freeze
# Only one public method for service object: #call
def call(input)
# Return if input is numeric (and don't forget to strip spaces and commas)
return input.gsub(/[\s,]/, '').to_f if float? input.gsub(/[\s,]/, '')
result = 0
# First line: insert spacebar if there is no one between integer and word
# Second line: split array by space
# Third line: convert each word to its numeric format
# Fourth line: slice array by 2 elements
# Fifth line: multiply each chunk and sum everything
input.gsub(/(?<=[\d])(?=[а-яА-Я])/, ' ')
.split(' ')
.map { |i| POWERS[i] ? POWERS[i].to_f : i.to_f }
.each_slice(2) do |slice|
result += slice.inject(:*)
end
result
end
private
# Check if given string may be converted to float
def float?(input)
input[/\A[\d]+[\.]?[\d]*\z/] == input
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment