1

我有一个输入列表[2,3,4,"5cm", 6,"2.5km"],我想要一个结果:

[2,3,4,5,6,2.5]

我想以这种方式开始

for element in inputList:
4

6 回答 6

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.05

>>> 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]
于 2013-06-16T16:46:51.367 回答
3
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"]

我希望解释能让你更清楚,发生了什么 - 如果没有,请在下面发表评论。

于 2013-06-16T16:47:32.650 回答
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]
于 2013-06-16T17:56:42.737 回答
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]
于 2013-06-16T17:25:20.123 回答
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]
于 2013-06-16T22:17:36.433 回答
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  
于 2013-06-16T17:44:21.250 回答