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

Python 当我的模式只包含一个组时,为什么re.findall返回元组列表?,python,regex,findall,Python,Regex,Findall,假设我有一个字符串s,包含字母和两个分隔符1和2。我想按以下方式拆分字符串: 如果子字符串t介于1和2之间,则返回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', ''), ('

假设我有一个字符串
s
,包含字母和两个分隔符
1
2
。我想按以下方式拆分字符串:

  • 如果子字符串
    t
    介于
    1
    2
    之间,则返回
    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', '')]

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

您的模式有两个组,一个较大的组:

(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']

您的正则表达式有2个组,只需查看您使用的括号数:)。一组是
([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']
>>重新导入
>>>s='ab1cd2efg1hij2k'

>>>关于findall(')((?类似问题的答案如下: 如果使用findall,只需删除括号即可:

import re
s = 'ab1cd2efg1hij2k'
re.findall( r'(?<=1)[a-z]+(?=2)|[a-z]', s )
重新导入
s='ab1cd2efg1hij2k'

关于re.findall(r’(?我参加派对已经晚了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上测试的。希望它能有所帮助!

如果您想在不将其拆分为匹配组的情况下进行“或”匹配,只需在“或”匹配的开头添加“?:”

没有“?:”

re.findall('(test (word1|word2))', 'test word1')

Output:
[('test word1', 'word1')]
带“?:”的

re.findall('(test (?:word1|word2))', 'test word1')

Output:
['test word1']

进一步说明:

只需做一个简单的更改:将组更改为非捕获组

代码:

输出:

['a', 'b', '1cd2', 'e', 'f', 'g', '1hij2', 'k']

您的模式非常奇怪。您不需要围绕
1
2
的非捕获组,也不需要围绕整个模式的组(您花费大量精力在输出中跳过)。相反,只需接受
findall
调用将返回两个元组,并将它们转换为带有
a=[x或y代表x,y代表a]
“非捕获组”是此处的关键字…(仅为搜索引擎添加)
['a', 'b', '1cd2', 'e', 'f', 'g', '1hij2', 'k']