我编写了以下代码,使所有20个字符的字符串都具有A、T、G和C的组合。
但是,我希望避免一行中超过3个相同的字符,因此我添加了一个if函数来检查这一点。问题是,这是在迭代工具代码之后,所以有点慢。我想知道是否有一种方法可以使用迭代工具来生成这个结果,而不必运行迭代工具,然后运行一个if函数?
import sys
import itertools
import re
x = ["A","T","G","C"]
for i in itertools.product(x, repeat=20):
i = "".join(i)
if re.search(r"(\w)\1\1",i):
continue
else:
sys.stdout.write(i)
发布于 2016-04-28 12:58:52
从表面上看,问题似乎是在问:
我如何过滤这个庞大的字符串列表,而不必先构造整个列表呢?
答案是:你已经在做了!itertools
中的东西产生延迟生成的序列,这些序列是迭代构造的。因此,您现有的代码不会产生数十亿字符串的庞大列表。
但你可能想问一个更有趣的问题:
如果我通过生成所有字符串并过滤出包含三胞胎的字符串来生成不含三重奏的字符串,那么我的代码将不得不做额外的工作,因为生成的大多数字符串中都包含三胞胎。假设字符串是按字典顺序生成的,那么前面的4**17将开始AAA,我们应该能够跳过所有这些。我们怎样才能做得更好?
不幸的是,如果您想这样做,那么您必须编写自己的代码才能做到这一点;itertools
不提供这种“模式过滤产品”功能。
它看起来可能是这样的:
# generate all n-tuples with the property that their k-th element
# is one of the things returned by successors(initial (k-1)-tuple).
# So e.g. the first element is one of the things returned by
# successors(()).
def restricted_tuples(successors, n):
assert(n>=0)
if n==0:
for t in successors(()): yield (t,)
else:
for start in restricted_tuples(successors, n-1):
for t in successors(start): yield start+(t,)
def successors_no_triples(start, alphabet):
if len(start)<2 or start[-1] != start[-2]:
for t in alphabet: yield t
else:
banned = start[-1]
for t in alphabet:
if t != banned: yield t
print([''.join(x) for x in restricted_tuples(lambda start: successors_no_triples(start,'ABC'), 5)])
最后的print
只是说明性的。如果您想要从原始发问者的案例中打印出所有的数十亿字符串,那么最好迭代restricted_tuples
生成的序列,并将每个字符串分别打印出来。
顺便提一句,有这个属性的4个字母上的长度-20序列的数目是415,289,569,968。如果您想要生成它们,特别是如果您真的想要对每一个都做任何事情的话,您将等待一段时间。
https://stackoverflow.com/questions/36915084
复制相似问题