Python Forum
stopping number conversion before end - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: stopping number conversion before end (/thread-28222.html)



stopping number conversion before end - Skaperen - Jul-09-2020

this function gets a str that has decimal digit characters followed by one alphabetic character that indicates how to multiply the number those digits represent. so, the function converts the digits and uses the letter to determine the other number to multiply and returns the product. for example: timedelta('12m') -> 720. what i am looking for is a pythonic way to convert the digits. could it be int(s[:-1])?

i am accustomed to a function in C (strtol,strtoul) that converts until it hits a non-digit and stores a pointer to the non-digit (literally one past the last converted digit). if i need to handle a case where there may be more than 1 character after the digits the Python code above is not enough. is there something good in Python to do that?

in Python, a reference to a string (or anything) can only refer to the whole string (or whole thing), never to a part of it.


RE: stopping number conversion before end - bowlofred - Jul-09-2020

I don't know a short-and-sweet method to do that. I would probably use a regex, since that easily stores the index of where it finds the first non-digit. But using something like itertools.takewhile or itertools.groupby with str.isdigit could also be used to split the string and rejoin the "integer" parts.


import re

s = "435xkb3"

if mo := re.match(r"(\d+)", s):   #Python 3.8 walrus operator.  Split into 2 lines for earlier versions.
    number = int(mo.group(1))
    print(f"The starting number is {number} and the rest begins at index {mo.end()}")
    print(f"the rest -> {s[mo.end():]}")
else:
    print(f"I couldn't find any integer at the start of the string")



RE: stopping number conversion before end - Skaperen - Jul-10-2020

the varying case i have at the moment is either a letter or no letter at all, so the simple code for this case is to use a try/except. try int(s) and if i get ValuError do int(s[:-1]). actually, for this one i'm using float(). i'll post code shortly. im just playing around. a boring evening so i'm coding random stuff.


RE: stopping number conversion before end - DeaD_EyE - Jul-10-2020

import itertools


def to_int(text):
    units = {"m": 60, "h": 3600, "k": 1000}
    value = int("".join(itertools.takewhile(lambda s: s.isdecimal(), text)))
    unit = "".join(itertools.dropwhile(lambda s: s.isdecimal(), text)).strip()
    value *= units.get(unit, 1)
    return value
or with regex

import re


def to_int(text):
    units = {"m": 60, "h": 3600, "k": 1000}
    if match := re.search(r"(?P<value>\d+)\s*?(?P<unit>\w+)", text):
        result = match.groupdict()
        value = int(result["value"])
        value *= units.get(result["unit"], 1)
        return value
A function for floats needs a different regex.
It's not so easy to make a correct regex to parse all possible floats.


RE: stopping number conversion before end - Skaperen - Jul-10-2020

i wish i could find something that would teach how to use regular expressions without using perl code.


RE: stopping number conversion before end - Gribouillis - Jul-12-2020

DeaD_EyE Wrote:It's not so easy to make a correct regex to parse all possible floats.
I have an old regex in my notes
r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?"



RE: stopping number conversion before end - DeaD_EyE - Jul-12-2020

Your regex is incomplete:

In [1]: import re                                                                                                            

In [2]: re.search(r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", "nan")                                                 

In [3]: float("nan")                                                                                                         
Out[3]: nan
This is nitpicking, but was in the past a big discussion why it's horrible to parse floats right with a regex.
The conclusion was: Don't ask for permission, ask for forgiveness.

But for this case, it's good enough. Working with dates should not result into a "nan" or "inf".