Python:如何只为字符串中的数字字符添加/减去数字?

时间:2017-03-09 19:19:59

标签: python string numeric alphanumeric

比如说,我有以下字符串和输入4.0,它代表秒:

John Time Made 11:05:20 in 2010
5.001 Kelly #1
6.005 Josh #8

并希望得到以下结果:

John Time Made 11:05:24 in 2010 #Input 4.0 is added to the seconds of 11:05:20
1.001 Kelly #1 #4.0 is subtracted from the first number 5.001 = 1.001
2.005 Josh #8 #4.0 is subtracted from the first number 5.001 = 2.005

如何识别第一行中的hours:minutes:seconds,并在其余部分#.###添加/减去输入数字?

提前感谢您,并接受/ upvote回答

2 个答案:

答案 0 :(得分:0)

如果您的完整数据与您提供的特定样本具有相同的格式,则此解决方案应该有效。您应该在input.txt文件中包含数据。

val_to_add = 4

with open('input.txt') as fin:
    # processing first line
    first_line = fin.readline().strip()
    splitted = first_line.split(' ')

    # get hour, minute, second corresponding to time (11:05:20)
    time_values = splitted[3].split(':')

    # seconds is the last element
    seconds = int(time_values[-1])

    # add the value
    new_seconds = seconds + val_to_add

    # doing simple math to avoid having values >= 60 for minute and second
    # this part probably can be solved with datetime or some other lib, but it's not that complex, so I did it in couple of lines
    seconds = new_seconds % 60 # if we get > 59 seconds we only put the modulo as second and the other part goes to minute
    new_minutes = int(time_values[1]) + new_seconds // 60 # if we have more than 60 s then here we'll add minutes produced by adding to the seconds
    minutes = new_minutes % 60 # similarly as for seconds
    hours = int(time_values[0]) + new_minutes // 60

    # here I convert again to string so we could easily apply join operation (operates only on strings) and additionaly add zero in front for 1 digit numbers
    time_values[0] = str(hours).rjust(2, '0')
    time_values[1] = str(minutes).rjust(2, '0')
    time_values[2] = str(seconds).rjust(2, '0')

    new_time_val = ':'.join(time_values)# join the values to follow the HH:MM:SS format
    splitted[3] = new_time_val# replace the old time with the new one (with the value added)
    first_line_modified = ' '.join(splitted)# just join the modified list

    print(first_line_modified)

    # processing othe lines
    for line in fin:
        # here we only get the first (0th) value and subtract the val_to_add and round to 3 digits the response (to avoid too many decimal places)
        stripped = line.strip()
        splitted = stripped.split(' ')
        splitted[0] = str(round(float(splitted[0]) - val_to_add, 3))
        modified_line = ' '.join(splitted)
        print(modified_line)

答案 1 :(得分:0)

虽然评论中不鼓励regex,但可以使用regex将时间对象解析为datetime.time个对象,对它们执行必要的计算,然后以所需格式打印它们:

# datetime module for time calculations
import datetime
# regex module
import re

# seconds to add to time
myinp = 4

# List of data strings
# data = 'John Time Made 11:05:20 in 2010', '5.001 Kelly', '6.005 Josh'

with open('data.txt') as f:
    data = f.readlines()

new_data = []

#iterate through the list of data strings
for time in data:
    try:
        # First check for 'HH:MM:SS' time format in data string
        #   regex taken from this question: http://stackoverflow.com/questions/8318236/regex-pattern-for-hhmmss-time-string
        match = re.findall("([0-1]?\d|2[0-3]):([0-5]?\d):([0-5]?\d)", time)
        # this regex returns a list of tuples as strings "[('HH', 'MM', 'SS')]", 
        #   which we join back together with ':' (colon) separators 
        t = ':'.join(match[0])
        # create a Datetime object from indexing the first matched time in the list,
        #   taken from this answer http://stackoverflow.com/questions/100210/what-is-the-standard-way-to-add-n-seconds-to-datetime-time-in-python
        # May create an IndexError exception, which we catch in the `except` clause below
        orig = datetime.datetime(100,1,1,int(match[0][0]), int(match[0][1]), int(match[0][2]))
        # Add the number of seconds to the Datetime object,
        #   taken from this answer: http://stackoverflow.com/questions/656297/python-time-timedelta-equivalent
        newtime = (orig + datetime.timedelta(0, myinp)).time()
        # replace the time in the original data string with the newtime and print
        new_data.append(time.replace(t, str(newtime)))
    # catch an IndexError Exception, which we look for float-formatted seconds only
    except IndexError:
        # look for float-formatted seconds (s.xxx)      
        #   taken from this answer: http://stackoverflow.com/questions/4703390/how-to-extract-a-floating-number-from-a-string 
        match = re.findall("\d+\.\d+", time)
        # create a Datetime object from indexing the first matched time in the list,
        #   specifying only seconds, and microseconds, which we convert to milliseconds (micro*1000)
        orig = datetime.datetime(100,1,1,second=int(match[0].split('.')[0]),microsecond=int(match[0].split('.')[1])*1000)
        # Subtract the seconds from the Datetime object, similiar to the time addtion in the `try` clause above
        newtime = orig - datetime.timedelta(0, myinp)
        # format the newtime as `seconds` concatenated with the milliseconds converted from microseconds
        newtime_fmt = newtime.second + newtime.microsecond/1000000.
        # Get the seconds value (first value(index 0)) from splitting the original string at the `space` between the `seconds` and `name` strings 
        t = time.split(' ')[0]
        # replace the time in the original data string with the newtime and print
        new_data.append(time.replace(t , str(newtime_fmt)))


with open('new_data.txt', 'w') as nf:
    for newline in new_data:
        nf.write(newline)

new_data.txt文件内容应为:

John Time Made 11:05:24 in 2010
1.001 Kelly
2.005 Josh