如何正确拆分这个字符串列表?

时间:2017-02-19 17:59:05

标签: python regex string list split

我有一个字符串列表,例如:

['z+2-44', '4+55+z+88']

如何在列表中拆分此字符串,使其类似于

[['z','+','2','-','44'],['4','+','55','+','z','+','88']]

我已尝试使用split方法但是将44分为4和4,我不知道还有什么可以尝试。

5 个答案:

答案 0 :(得分:26)

您可以使用正则表达式:

import re
lst = ['z+2-44', '4+55+z+88']
[re.findall('\w+|\W+', s) for s in lst]
# [['z', '+', '2', '-', '44'], ['4', '+', '55', '+', 'z', '+', '88']]

\w+|\W+匹配一个模式,该模式包含单词字符(在您的情况下为字母数字值)或非单词字符(在您的情况下为+-符号)。

答案 1 :(得分:14)

这将有效,使用itertools.groupby

z = ['z+2-44', '4+55+z+88']

print([["".join(x) for k,x in itertools.groupby(i,str.isalnum)] for i in z])

输出:

[['z', '+', '2', '-', '44'], ['4', '+', '55', '+', 'z', '+', '88']]

它只是将字符分组,如果它们是字母数字(或不是字母数字),只需将它们加入列表理解中即可。

编辑:带有括号的计算器的一般情况已被要求作为后续问题here。如果z如下:

z = ['z+2-44', '4+55+((z+88))']

然后我们得到了之前的分组:

[['z', '+', '2', '-', '44'], ['4', '+', '55', '+((', 'z', '+', '88', '))']]

在令牌方面解析起来并不容易。因此,只有在使用alphanum时才会更改为join,如果不是,则列出最后使用chain.from_iterable进行展平:

print([list(itertools.chain.from_iterable(["".join(x)] if k else x for k,x in itertools.groupby(i,str.isalnum))) for i in z])

产生:

[['z', '+', '2', '-', '44'], ['4', '+', '55', '+', '(', '(', 'z', '+', '88', ')', ')']]

(请注意,备用正则表达式答案也可以这样调整:[re.findall('\w+|\W', s) for s in lst](注意+之后缺少W

"".join(list(x))也比"".join(x)略快,但是我允许你添加它以避免改变已经复杂的表达式的可见性。

答案 2 :(得分:6)

使用re.split函数的替代解决方案:

l = ['z+2-44', '4+55+z+88']
print([list(filter(None, re.split(r'(\w+)', i))) for i in l])

输出:

[['z', '+', '2', '-', '44'], ['4', '+', '55', '+', 'z', '+', '88']]

答案 3 :(得分:5)

您只能在列表理解中使用str.replace()str.split()内置函数:

In [34]: lst = ['z+2-44', '4+55+z+88']

In [35]: [s.replace('+', ' + ').replace('-', ' - ').split() for s in lst]
Out[35]: [['z', '+', '2', '-', '44'], ['4', '+', '55', '+', 'z', '+', '88']]

但请注意,对于较长的字符串,这不是一种有效的方法。在这种情况下,最好的方法是使用正则表达式。

作为另一种pythonic方式,您还可以使用tokenize模块:

In [56]: from io import StringIO

In [57]: import tokenize

In [59]: [[t.string for t in tokenize.generate_tokens(StringIO(i).readline)][:-1] for i in lst]
Out[59]: [['z', '+', '2', '-', '44'], ['4', '+', '55', '+', 'z', '+', '88']]
  

Python comparison operators chaining模块为Python源代码提供了一个词法扫描程序,用Python实现。此模块中的扫描仪也将注释作为标记返回,这使得它可用于实现“漂亮的打印机”,包括用于屏幕显示的着色器。

答案 4 :(得分:-1)

如果你想坚持使用split(因此避免使用正则表达式),你可以为它提供一个可选字符来分割:

>>> testing = 'z+2-44'
>>> testing.split('+')
['z', '2-44']
>>> testing.split('-')
['z+2', '44']

所以,你可以通过链接拆分命令来鞭打一些东西。

但是,使用正则表达式可能更具可读性:

import re

>>> re.split('\+|\-', testing)
['z', '2', '44']

这只是说"将字符串拆分为任何+或 - 字符" (反斜杠是转义字符,因为它们在正则表达式中都有特殊含义。

最后,在这种特殊情况下,我认为目标是"在每个非字母数字字符处分开",在这种情况下,正则表达式仍然可以节省一天:

>>> re.split('[^a-zA-Z0-9]', testing)
['z', '2', '44']

当然值得注意的是,正如其他一些SO讨论所讨论的那样,还有其他一百万个解决方案。

Python: Split string with multiple delimiters

Split Strings with Multiple Delimiters?

我的答案是针对简单易读的代码,而不是表现,以纪念Donald Knuth