使用正则表达式可能会为您提供解决此问题的最简洁的代码。简洁性是难以超越的
re.findall(r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?", str)
来自 pythad 的回答。
但是,您说“我试图避免使用正则表达式”,所以这里有一个不使用正则表达式的解决方案。它显然比使用正则表达式的解决方案要长一点(而且可能要慢得多),但并不复杂。
代码逐个字符地循环输入。
当它从字符串中提取每个字符时,它会将其附加到current(一个包含当前正在解析的数字的字符串)if 附加它仍然保持有效数字。当遇到无法附加到current 的字符时,current 会保存到数字列表中,但前提是current 本身不是''、'.'、'-' 或@ 之一987654329@;这些是可能以数字开头但本身不是有效数字的字符串。
保存current 时,将删除结尾的'e'、'e-' 或'e+'。这将发生在诸如'1.23eA' 之类的字符串中。在解析该字符串时,current 最终会变为'1.23e',但随后遇到了'A',这意味着该字符串不包含有效的指数部分,因此'e' 被丢弃。
保存current后,会被重置。通常current被重置为'',但是当触发current被保存的字符是'.'或'-'时,current被设置为那个字符,因为这些字符可能是一个新号码。
这是函数extract_numbers(s)。 return numbers 之前的行将字符串列表转换为整数和浮点值列表。如果您只想要字符串,请删除该行。
def extract_numbers(s):
"""
Extract numbers from a string.
Examples
--------
>>> extract_numbers("Hello4.2this.is random 24 text42")
[4.2, 24, 42]
>>> extract_numbers("2.3+45-99")
[2.3, 45, -99]
>>> extract_numbers("Avogadro's number, 6.022e23, is greater than 1 million.")
[6.022e+23, 1]
"""
numbers = []
current = ''
for c in s.lower() + '!':
if (c.isdigit() or
(c == 'e' and ('e' not in current) and (current not in ['', '.', '-', '-.'])) or
(c == '.' and ('e' not in current) and ('.' not in current)) or
(c == '+' and current.endswith('e')) or
(c == '-' and ((current == '') or current.endswith('e')))):
current += c
else:
if current not in ['', '.', '-', '-.']:
if current.endswith('e'):
current = current[:-1]
elif current.endswith('e-') or current.endswith('e+'):
current = current[:-2]
numbers.append(current)
if c == '.' or c == '-':
current = c
else:
current = ''
# Convert from strings to actual python numbers.
numbers = [float(t) if ('.' in t or 'e' in t) else int(t) for t in numbers]
return numbers