我正在尝试将包含2个不同字符序列的字符串拆分成组。如果我们假设字符为a
和b
,则分组的纯文本规则为:
a
组成,后跟1 + b
a
都包含在下一组中,除非我们在该词的末尾。例如:处理tests
后,目标是分成expected
组。
tests = ['abab',
'ababab',
'aabab',
'aababa',
'aba',
'baba']
expected = [['ab','ab'],
['ab','ab','ab'],
['aab','ab'],
['aab','aba'],
['aba'],
['b','aba']]
我得到的最接近的是:
import re
# filter() returns iterator not list in Python 3
def testing(s):
return list(filter(None, re.compile('(a*b+a*(?=$))').split(s)))
output = [testing(s) for s in tests]
output
[['ab', 'ab'], ['abab', 'ab'], ['aab', 'ab'], ['aab', 'aba'], ['aba']]
哪一组在1-2组中表现良好,但对于大于此组的组则不然,这意味着我的正则表达式需要改进。我应该重新考虑这种方法吗?我可以用for循环做一些暴力但是希望有更优雅的东西。
N.B。:This post让我相信.split()可能不是这里的方式,但到目前为止我已经获得了最好的结果。
答案 0 :(得分:3)
我相信你走在了正确的轨道上。但是,你的正则表达式比你想象的还要多。您的测试用例并未涵盖所有可能的情况,因此您没有意识到这一点。
由于您有几个特殊情况,您应该单独处理它们。例如,最后一个输入是特殊情况,因为它匹配aba
。同样,单独列出其他内容并将其与|
一起加入。您也可以使用re.findall
,它更清洁。
tests = ['abab',
'ababab',
'aabab',
'aababa',
'aba',
'baba']
def testing(s):
return re.findall('(?:a*b+a+$)|(?:a*b+)|(?:b+a+)', s)
output = [testing(s) for s in tests]
print(output)
输出:
[['ab', 'ab'], ['ab', 'ab', 'ab'], ['aab', 'ab'], ['aab', 'aba'], ['aba'], ['b', 'aba']]
答案 1 :(得分:1)
这给出了测试数据的正确结果:
tests = ['abab',
'ababab',
'aabab',
'aababa',
'aba',
'baba',
'abba']
for s in tests:
r = re.findall("(?:a*b+a*$)|(?:a*b+)",s)
print(r)
结果:
['ab', 'ab']
['ab', 'ab', 'ab']
['aab', 'ab']
['aab', 'aba']
['aba']
['b', 'aba']
['abba']