分割一个字符重复两次的序列

时间:2018-07-19 20:10:44

标签: python regex python-3.x

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

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

2 个答案:

答案 0 :(得分:4)

使用itertools.groupby代替正则表达式:

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

答案 1 :(得分:1)

使用re.findall

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

主要思想是编写一个始终成功的模式,这样,正则表达式引擎不必使用4个替代方法(aa,cc,gg,tt +环顾四周)来测试字符串中的每个位置,而大多数情况下时间。所有比赛都是连续的。

模式有两个部分,第一个(?:(.)(?!\2)|(.)\3\3+)+描述了不完全是两个相同字符(单个字符(.)(?!\2)或两个以上相同字符(.)\3\3+)的所有内容,并重复了贪婪地将第二部分与..

匹配

如果需要,可以用[actg]替换所有点。


re.finditer

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

或从Python 3.6开始:

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