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 valueor 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 valueA 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]: nanThis 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". |