craigeley
craigeley

Reputation: 352

Find Numeric Values in Ruby and then Convert them to Strings

I have files that have a bunch of lines containing text and numbers. The text in each file stays the same, but the numbers change. (This is running data, so the lines are things like "- Active Duration 28:19, - Total distance 3.66mi.", etc.)

What I want to do is locate the individual numbers in these lines, then create my own output, such as: "Ran #{distance} in #{time}"

I'm able to locate these numbers in the lines using regular expressions, but I cannot figure out how to then take those values and make them into their own strings. I'm not even sure regex is the right approach. I've been running things like this:

if line =~/\d*\.\d*/
found completed = true

But then I'm not sure what comes next.

I hope I'm being clear—and thanks in advance for your help.

Upvotes: 1

Views: 110

Answers (3)

Stephen
Stephen

Reputation: 103

Updated answer to show iteration over file.

I put the results into a hash so that key-value pairs could be utilised for the manipulation of the data. New keys could be added for the unit of measurement, etc.

runData_20130620.txt
-Active Duration 09.87, -Total Distance 100.0m
-Active Duration 15:19, -Total Distance 4.98km
-Active Duration 03:00, -Total Distance 1.0mile
-Active Duration 21:14, -Total Distance 3.68, -Sweat Produced 5.99Gallons
-Active Duration 22:31, -Total Distance 3.65mi

Code

File.foreach("runData_20130620.txt") do |line|

    # Create hash, parsing string with regex pattern
    runData = Hash[*line.scan(/([^, \-]\D*) (\d*[.:]\d*)/).to_a.flatten]

    # This will convert the string keys to symbols, replacing white-space with 
    # underscores and downcasing

    runData = Hash[runData.map { |k,v|
                        [k.gsub(/\s+/, "_").downcase.to_sym, v] }] 

    # display results
    #runData.each { |k,v| puts "#{k} ** #{v}" }

    # display using hash symbol access...
    puts "\nRan a distance of #{ runData[:total_distance]} in
                                               runData[:active_duration]} "
    puts "Man, I am unfit!" if runData[:sweat_produced]
end

Results

Ran a distance of 100.0 in 09.87

Ran a distance of 4.98 in 15:19

Ran a distance of 1.0 in 03:00

Ran a distance of 3.68 in 21:14
Man, I am unfit!

Ran a distance of 3.65 in 22:31

Upvotes: 1

BigLoppy
BigLoppy

Reputation: 126

You can use regex in the element reference to get the number data. For example:

2.0.0-p0 :010 > distance = line[/\d*\.\d*/]
=> "3.66" 
2.0.0-p0 :011 > time = line[/\d*:\d*/]
 => "28:19" 
2.0.0-p0 :012 > puts "Ran #{distance} in #{time}"
Ran 3.66 in 28:19
 => nil

Upvotes: 2

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89639

You can do that:

rawlines = <<EOF
- Active Duration 28:19, - Total distance 3.66mi.
- Active Duration 25:12, - Total distance 3.66mi.
- Active Duration 24:10, - Total distance 3.66mi.
- Active Duration 28:21, - Total distance 3.66mi.
- Active Duration 27:19, - Total distance 3.66mi.
EOF

rawlines.scan(/Active Duration (\d++:\d++), - Total distance (\d++(?>\.\d++)?)/) do |dur, dist|
  puts "Ran #{dist} in #{dur}\n"
end

Upvotes: 1

Related Questions