拆分一个字符正好重复两次的序列



我想拆分一个字符重复两次的序列,并保留分隔部分。有一个较短的正则表达式吗?

In [101]: seq='tgtttccgagtgacccgagatagaaacttaccgga'
In [102]: l=[ s for s in re.split(r"(?<!a)(a{2})(?!a)|(?<!g)(g{2})(?!g)|(?<!c)(c{2})(?!c)|(?<!t)(t{2})(?!t)",seq) if s ]
In [103]: l
Out[103]: ['tgttt', 'cc', 'gagtgacccgagatagaaac', 'tt', 'a', 'cc', 'gg', 'a']
In [104]: ''.join(l)==seq
Out[104]: True

使用itertools.groupby:而不是regex

import itertools
def get_combos(d):
for a, b in d:
if a:
yield from b
else:
yield ''.join(b)
seq='tgtttccgagtgacccgagatagaaacttaccgga'
new_seq = [''.join(b) for _, b in itertools.groupby(seq)]
final_result = list(get_combos([[a, list(b)] for a, b in itertools.groupby(new_seq, key=lambda x:len(x) == 2 and x[0] == x[1])]))

输出:

['tgttt', 'cc', 'gagtgacccgagatagaaac', 'tt', 'a', 'cc', 'gg', 'a']

使用re.findall:

>>> import re
>>> seq='tgtttccgagtgacccgagatagaaacttaccgga'
>>> [m[0] for m in re.findall(r'((?:(.)(?!2)|(.)33+)+|..)', seq)]
['tgttt', 'cc', 'gagtgacccgagatagaaac', 'tt', 'a', 'cc', 'gg', 'a']

其主要思想是编写一个始终成功的模式,这样,正则表达式引擎就不必在大多数情况下用4个备选方案(aa、cc、gg、tt+查找(来测试字符串中的每个位置。所有的比赛都是连续的。

该模式有两个部分,第一个(?:(.)(?!2)|(.)33+)+描述了所有不是完全相同的两个字符(单个字符(.)(?!2)或两个以上相同的字符(.)33+(并且贪婪地重复,第二部分将剩余的情况与..相匹配

如果需要,可以随意将所有点替换为[actg]


re.finditer:

[mo.group(0) for mo in re.finditer(r'(?:(.)(?!1)|(.)22+)+|..', seq)]

或者从Python 3.6开始:

[mo[0] for mo in re.finditer(r'(?:(.)(?!1)|(.)22+)+|..', seq)]

最新更新