当我的模式只包含一个组时,为什么re.findall会返回元组列表?

问题描述 投票:4回答:4

说我有一个字母s包含字母和两个分隔符12。我想以下列方式拆分字符串:

  • 如果一个子串t落在12之间,返回t
  • 否则,返回每个字符

因此,如果s = 'ab1cd2efg1hij2k',预期的输出是['a', 'b', 'cd', 'e', 'f', 'g', 'hij', 'k']

我试图使用正则表达式:

import re
s = 'ab1cd2efg1hij2k'
re.findall( r'(1([a-z]+)2|[a-z])', s )

[('a', ''),
 ('b', ''),
 ('1cd2', 'cd'),
 ('e', ''),
 ('f', ''),
 ('g', ''),
 ('1hij2', 'hij'),
 ('k', '')]

从那里我可以做[ x[x[-1]!=''] for x in re.findall( r'(1([a-z]+)2|[a-z])', s ) ]得到我的答案,但我仍然不明白输出。 documentation说,如果模式有多个组,findall会返回一个元组列表。但是,我的模式只包含一个组。欢迎任何解释。

python regex findall
4个回答
5
投票

你的模式有两组,更大的组:

(1([a-z]+)2|[a-z])

以及第二个较小的组,它是您第一组的子集:

([a-z]+)

这是一个给你预期结果的解决方案,但是请注意,它真的很难看,而且可能有更好的方法。我只是想不出来:

import re
s = 'ab1cd2efg1hij2k'
a = re.findall( r'((?:1)([a-z]+)(?:2)|([a-z]))', s )
a = [tuple(j for j in i if j)[-1] for i in a]

>>> print a
['a', 'b', 'cd', 'e', 'f', 'g', 'hij', 'k']

1
投票

你的正则表达式有两组,只看你正在使用的括号数:)。一组是([a-z]+),另一组是(1([a-z]+)2|[a-z])。关键是你可以在其他组中包含组。因此,如果可能,您应该只使用一个组构建正则表达式,这样您就不必对结果进行后处理。

只有一个组的正则表达式示例如下:

>>> import re
>>> s = 'ab1cd2efg1hij2k'
>>> re.findall('((?<=1)[a-z]+(?=2)|[a-z])', s)
['a', 'b', 'cd', 'e', 'f', 'g', 'hij', 'k']

1
投票

我在派对上已经晚了5年,但我想我可能已经找到了一个优雅的解决方案来处理带有多个捕获组的re.findall()丑陋的元组循环输出。

一般来说,如果你得到一个看起来像这样的输出:

[('pattern_1', '', ''), ('', 'pattern_2', ''), ('pattern_1', '', ''), ('', '', 'pattern_3')]

然后你可以用这个小技巧将它带入一个平面列表:

["".join(x) for x in re.findall(all_patterns, iterable)]

预期的输出将是这样的:

['pattern_1', 'pattern_2', 'pattern_1', 'pattern_3']

它在Python 3.7上进行了测试。希望能帮助到你!


0
投票

看看这个类似问题的答案:https://bugs.python.org/issue6663如果你使用findall,只需删除括号:

import re
s = 'ab1cd2efg1hij2k'
re.findall( r'(?<=1)[a-z]+(?=2)|[a-z]', s )
© www.soinside.com 2019 - 2024. All rights reserved.