我有一个像[2,3,4,"5cm", 6,"2.5km"]
这样的输入列表,我希望得到一个结果:
[2,3,4,5,6,2.5]
我想以这种方式开始
for element in inputList:
答案 0 :(得分:5)
您可以使用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]
答案 1 :(得分:4)
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
此解决方案使用regular expressions从字符串中提取数字部分。 re
是一个非常有用的模块,您应该定义自己的模型。
因为正则表达式只适用于字符串,所以我们首先必须将那些数字的列表元素转换为字符串。我们使用list comprehension:[str(i) for i in inputList]
如果你写print [str(i) for i in inputList]
,那么你会得到:
["2", "3", "5", "2", "2.5km", "3cm"]
所以这几乎和以前一样,但数字现在是字符串。
现在,使用它我们可以创建一个识别数字的正则表达式。我自己没有提出这个问题,而是来自here(%f
)。我们将字符串化列表中的每个元素与该模式匹配,并将结果字符串转换为我们附加到float
的{{1}}。
请注意,在某些区域设置中,小数点(outputList
)可能由不同的字符表示。如果这在您的情况下很重要,您可以按如下方式接收当前的语言环境小数点字符:
\.
我希望这个解释能让你更清楚,发生了什么 - 如果没有,请在下面发表评论。
答案 2 :(得分:1)
这是一个不使用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]
答案 3 :(得分:1)
首先,使用正则表达式:它是正确的工具。其次,使用最适合您已知需求的最简单解决方案:具体来说,我们可以使用正则表达式从字符串末尾删除非数字。
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]
答案 4 :(得分:0)
如果你不能忍受正则表达式,那么还有一个(可能是最不优雅的):
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
答案 5 :(得分:0)
这是一个受@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]