如何从字符串列表中提取数字?

3

我该如何从以下文本中提取数字:

a = ['1 2 3', '4 5 6', 'invalid']

我已经尝试过:

mynewlist = [s for s in a if s.isdigit()]
print mynewlist

并且。
for strn in a:
    values = map(float, strn.split())
print values

两者都失败了,因为数字之间有一个空格。

注意:我试图实现以下输出:

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

数字仅由空格分隔,还是您希望可能会有其他东西,例如逗号或其他字符? - Dunno
你使用 values = map(float, strn.split()) 得到了什么? - levi
@Dunno:是的,它们是用空格分隔而不是逗号。 - labmat
@levi 我得到了 ValueError: 无法将字符串转换为浮点数: 无效。 - labmat
1
在这种情况下,为什么你的代码无法工作很明显并不重要,但是你应该养成在 SO 问题中包含完整的堆栈跟踪和详细描述代码失败原因的习惯。当你将来询问更复杂的问题时,仅仅说你的代码“失败”可能会导致问题被关闭,因为这远远不够详细。 - skrrgwasme
7个回答

9
我认为你需要将list中的每个项目作为以空格为分隔符的字符串进行处理。
a = ['1 2 3', '4 5 6', 'invalid']
numbers = []
for item in a:
    for subitem in item.split():
        if(subitem.isdigit()):
            numbers.append(subitem)
print(numbers)

['1', '2', '3', '4', '5', '6']

或者简洁明了地理解为:
[item for subitem in a for item in subitem.split() if item.isdigit()]

3

对于你的特定情况来说,这样做就可以了,因为你在列表中包含了一个字符串。因此,你需要将它展开:

new_list = [int(item) for sublist in a for item in sublist if item.isdigit()]

1
对于输入如 ['25 33 48'],这将产生类似 [2, 5, 3, 3, 4, 8] 的输出。 - Patrick Haugh

3
假设列表中只有字符串:
[int(word) for sublist in map(str.split, a) for word in sublist if word.isdigit()]

2

借助集合,您可以实现以下功能:

>>> a = ['1 2 3', '4 5 6', 'invalid']
>>> valid = set(" 0123456789")
>>> [int(y) for x in a if set(x) <= valid for y in x.split()]
[1, 2, 3, 4, 5, 6]

如果字符串由valid集合中的字符组成,那么这将仅包括来自字符串中的数字。


@eugene y:现在这个可以用了!感谢您的审查和努力! :) - labmat

0
mynewlist = [s for s in a if s.isdigit()]
print mynewlist

不起作用是因为您正在迭代数组的内容,该数组由三个字符串组成:

  1. '1 2 3'
  2. '4 5 6'
  3. 'invalid'

这意味着您必须再次迭代每个字符串。

您可以尝试类似以下的代码:

mynewlist = []
for s in a:
    mynewlist += [digit for digit in s if digit.isdigit()] 

在变量名中,应避免使用“array”这个词来表示列表。数组和列表是不同的数据结构,具有不同的属性和功能。 - skrrgwasme
有没有早期的修订版本使用它?因为现在它不在那里,也不在问题修订历史中。 - skrrgwasme

0

一行代码解决方案:

new_list = [int(m) for n in a for m in n if m in '0123456789']

0

从字符串列表中提取数字有很多选项。

假设一般的字符串列表如下:

input_list = ['abc.123def45, ghi67 890 12, jk345', '123, 456 78, 90', 'abc def, ghi'] * 10000

如果不考虑转换为整数,

def test_as_str(input_list):
    output_list = []
    
    for string in input_list:
        output_list += re.findall(r'\d+', string)
    
    return output_list

%timeit -n 10 -r 7 test_as_str(input_list)
> 37.6 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_str(input_list):
    output_list = []
    
    [output_list.extend(re.findall(r'\d+', string)) for string in input_list]
    
    return output_list

%timeit -n 10 -r 7 test_as_str(input_list)
> 39.5 ms ± 118 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_str(input_list):
    return list(itertools.chain(*[re.findall(r'\d+', string) for string in input_list]))

%timeit -n 10 -r 7 test_as_str(input_list)
> 40.4 ms ± 202 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_str(input_list):
    return list(filter(None, [item for string in input_list for item in re.split('[^\d]+' , string)]))

%timeit -n 10 -r 7 test_as_str(input_list)
> 42.8 ms ± 372 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

整数转换也可以考虑。

def test_as_int(input_list):
    output_list = []
    
    for string in input_list:
        output_list += re.findall(r'\d+', string)
    
    return list(map(int, output_list))

%timeit -n 10 -r 7 test_as_int(input_list)
> 44.7 ms ± 232 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_int(input_list):
    output_list = []
    
    for string in input_list:
        output_list += re.findall(r'\d+', string)
    
    return [int(item) for item in output_list]

%timeit -n 10 -r 7 test_as_int(input_list)
> 47.8 ms ± 198 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_int(input_list):
    return [int(item) for string in input_list for item in re.findall(r'\d+', string)]

%timeit -n 10 -r 7 test_as_int(input_list)
> 48.3 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_int(input_list):
    return [int(item) for string in input_list for item in re.split('[^\d]+' , string) if item]

%timeit -n 10 -r 7 test_as_int(input_list)
> 51.4 ms ± 150 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_int(input_list):
    return [int(item) for string in input_list for item in re.split('[^\d]+' , string) if item.isdigit()]

%timeit -n 10 -r 7 test_as_int(input_list)
> 54.9 ms ± 210 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

def test_as_int(input_list):
    return [int(item) for string in input_list for item in re.split('[^\d]+' , string) if len(item)]

%timeit -n 10 -r 7 test_as_int(input_list)
> 55.5 ms ± 175 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

性能测试在 Windows 操作系统、Python 3.8.8 虚拟环境下进行,结果差异不大。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接