我有一个输入列表[2,3,4,"5cm", 6,"2.5km"]
,我想要一个结果:
[2,3,4,5,6,2.5]
我想以这种方式开始
for element in inputList:
您可以使用regex
:
>>> import re
>>> lis = [2,3,4,"5cm", 6,"2.5km"]
>>> r = re.compile(r'\d+(.\d+)?')
>>> [float(r.search(x).group(0)) if isinstance(x,str) else x for x in lis]
[2, 3, 4, 5.0, 6, 2.5]
使用而ast.literal_eval
不是float
得到5.0
:5
>>> from ast import literal_eval
>>> [literal_eval(r.search(x).group(0)) if isinstance(x,str) else x for x in lis]
[2, 3, 4, 5, 6, 2.5]
开始你的方式:
import re
from ast import literal_eval
ans = []
r = re.compile(r'\d+(.\d+)?') #regex to match an integer or decimal
inputList = [2,3,4,"5cm", 6,"2.5km"]
for element in inputList:
if isinstance(element, str): #if element is a string then apply the regex
num = r.search(element).group(0)
ans.append(literal_eval(num))
else:
ans.append(element) #else append the element as it is
print ans
#[2, 3, 4, 5, 6, 2.5]
另一种解决方案,考虑到您的输入始终是有效的:
>>> from string import digits
>>> allowed = '-+.' + digits
>>> allowed #allowed characters
'-+.0123456789'
>>> lis = [2,3,4,"5cm", 6,"2.5km"]
>>> ans = []
for item in lis:
if isinstance(item, str):
# if item is a string
num = '' # Initialize an empty string
for c in item: # Iterate over the string, one character at time.
if c in allowed: # If the character is present in `allowed` then
num += c # concatenate it to num
else:
break # else break out of loop
ans.append(float(num)) # Append the float() output of `num` to `ans` or use
# `ast.literal_eval`
else:
ans.append(item)
...
>>> ans
[2, 3, 4, 5.0, 6, 2.5]
import re
inputList = [2, 3, 5, "2", "2.5km", "3cm"]
outputList = []
for element in [str(i) for i in inputList]:
match = re.match(r"([-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?).*", element)
if match:
outputList.append(float(match.group(1)))
print outputList
此解决方案使用正则表达式从字符串中提取数字部分。re
是一个非常有用的模块,您一定要熟悉它。
因为正则表达式仅适用于字符串,所以我们首先必须将那些为数字的列表元素转换为字符串。我们这样做,使用列表推导:[str(i) for i in inputList]
如果你写print [str(i) for i in inputList]
,那么你会得到:
["2", "3", "5", "2", "2.5km", "3cm"]
所以它几乎和以前的列表一样,但数字现在是字符串。现在,使用它我们可以创建一个识别数字的正则表达式。这个不是我自己编的,是从这里(%f
)。我们将字符串化列表中的每个元素与该模式匹配,并将结果字符串转换为float
我们附加到outputList
.
请注意,在某些语言环境中,小数点 ( \.
) 可能由不同的字符表示。如果这对您的情况很重要,您可以接收当前的语言环境小数点字符,如下所示:
import locale
locale.localeconv()["decimal_point"]
我希望解释能让你更清楚,发生了什么 - 如果没有,请在下面发表评论。
首先,使用正则表达式:它是工作的正确工具。其次,使用适合您已知要求的最简单的解决方案:具体来说,我们可以使用正则表达式从字符串末尾删除非数字。
import re
vals = [2, 3, 4, "5cm", 6, "2.5km"]
rgx = re.compile(r'\D+$')
nums = [float( rgx.sub('', str(v)) ) for v in vals]
print nums
如果你真的必须避免使用正则表达式,这里有一种方法可以避免使用异常处理、类型检查或任何比最简单的逻辑更复杂的逻辑if-else
。
def leading_digits(v):
for c in str(v):
if c in '0123456789.': yield c
else: return
def intfloat(s):
f = float(s)
i = int(f)
return i if i == f else f
vals = [2, 3, 4, "5cm", 6, "2.5km", '8.77cm extra junk w/ digits 44']
nums = [intfloat(''.join(leading_digits(v))) for v in vals]
print nums # [2, 3, 4, 5, 6, 2.5, 8.77]
这是一个不使用regex
:的解决方案
my_list = [2,3,4,"5cm", 6,"2.5km"]
def get_digits(s):
return ''.join(ele for ele in s if not ele.isalpha())
def convert_to_nums(my_list):
result = []
for ele in my_list:
if isinstance(ele, (int, float)):
result.append(ele)
else:
ele = get_digits(ele)
try:
result.append(int(ele))
except ValueError:
result.append(float(ele))
return result
结果:
>>> convert_to_nums(my_list)
[2, 3, 4, 5, 6, 2.5]
这是一个受@Akavall 启发并简化为的解决方案ast.literal_eval
:
from ast import literal_eval
def get_digits(s):
return ''.join(ele for ele in s if not ele.isalpha())
def convert_to_nums(my_list):
return [literal_eval(d) for d in (get_digits(s) for s in map(str, my_list))]
结果:
>>> my_list = [2,3,4,"5cm", 6,"2.5km"]
>>> convert_to_nums(my_list)
[2, 3, 4, 5, 6, 2.5]
如果您不能忍受正则表达式,这里还有一个(可能是最不优雅的):
input = [2,3,4,"5cm", 6,"2.5km"]
result = list()
for ele in input:
while type(ele) is str:
ele = ele[:-1] # Strip off one letter from the end.
for tt in (int, float):
try:
ele = tt(ele)
break
except:
pass
result.append(ele)
print result