我写了这个野蛮的脚本来创建一串字符的排列,这些字符在字符串中所有可能的位置组合中包含n(最多n = 4)$。我最终将.replace('$','(\\w)')
用于dna搜索序列中的不匹配。由于我编写脚本的方式,一些排列少于请求的$的数量。然后我编写了一个脚本来删除它们,但它似乎没有效果,每次运行删除脚本时,它都会删除更多不需要的排列。在下面粘贴的代码中,您将看到我使用4个不匹配的简单序列测试函数。然后我运行一系列删除脚本,计算每次删除多少表达式...根据我的经验,删除所有表达式少于4张外卡的$表达式大约需要8次。我有几个问题:
是否有内置函数用于'n'不匹配的搜索?也许甚至在biopython中?到目前为止,我已经看过Paul_McGuire_regex函数:
Search for string allowing for one mismatch in any location of the string,
这似乎只会产生1个不匹配。我必须承认,我并不完全理解该页面上剩余功能中的所有代码,因为我是一个非常新的编码器。
因为我认为这对我来说是一个很好的练习,是否有更好的方法来编写整个脚本?...我可以根据需要多次迭代Paul_McGuire_regex函数吗?
最令我困惑的是,为什么删除脚本第一次不会100%工作?
感谢您提供的任何帮助!
def Mismatch(Search,n):
List = []
SearchL = list(Search)
if n > 4:
return("Error: Maximum of 4 mismatches")
for i in range(0,len(Search)):
if n == 1:
SearchL_i = list(Search)
SearchL_i[i] = '$'
List.append(''.join(SearchL_i))
if n > 1:
for j in range (0,len(Search)):
if n == 2:
SearchL_j = list(Search)
SearchL_j[i] = '$'
SearchL_j[j] = '$'
List.append(''.join(SearchL_j))
if n > 2:
for k in range(0,len(Search)):
if n == 3:
SearchL_k = list(Search)
SearchL_k[i] = '$'
SearchL_k[j] = '$'
SearchL_k[k] = '$'
List.append(''.join(SearchL_k))
if n > 3:
for l in range(0,len(Search)):
if n ==4:
SearchL_l = list(Search)
SearchL_l[i] = '$'
SearchL_l[j] = '$'
SearchL_l[k] = '$'
SearchL_l[l] = '$'
List.append(''.join(SearchL_l))
counter=0
for el in List:
if el.count('$') < n:
counter+=1
List.remove(el)
return(List)
List_RE = Mismatch('abcde',4)
counter = 0
for el in List_RE:
if el.count('$') < 4:
List_RE.remove(el)
counter+=1
print("Filter2="+str(counter))
答案 0 :(得分:3)
我们可以通过回答问题1来解决问题2和问题3,但是理解问题3很重要,所以我先做,然后展示如何完全避免它:
关于问题3,这是因为当您在python中循环遍历列表并在循环中对其进行更改时,循环的列表会发生变化。
来自python docs on control flow (for statement section):
不安全修改循环中迭代的序列 (这只能发生在可变序列类型中,例如列表)。
说出您的列表为[a,b,c,d]
,然后使用for el in List
循环显示该列表。
说el
目前是a
,而你List.remove(el)
。
现在,您的列表为[b,c,d]
。但是,迭代器指向列表中的第二个元素(因为它是第一个完成的),现在是c
。
从本质上讲,您已跳过b
。所以问题是你正在修改你正在迭代的列表。
有几种方法可以解决这个问题:如果你的List
复制成本不高,你可以复制一份。所以迭代List[:]
,但要从List
中删除。
但是假设一直复制List
是很昂贵的。
然后你做的是迭代向后。请注意下面的reversed
:
for el in reversed(List):
if el.count('$') < n:
counter+=1
List.remove(el)
return(List)
在上面的示例中,假设我们在List
上向后迭代。
迭代器从d
开始,然后转到c
。
假设我们删除c
,以便List=[a,b,d]
。
由于迭代器向向后,它现在指向元素b
,所以我们没有跳过任何东西。
基本上,这可以避免修改你尚未迭代的列表中的位。
如果我正确理解您的问题,您基本上想要从n
个位置中选择m
,其中m
是字符串的长度(abcde
),并且在这些n
个职位中加上'$'。
在这种情况下,您可以使用itertools
模块来执行此操作。
import itertools
def Mismatch(Search,n):
SearchL = list(Search)
List = [] # hold output
# print list of indices to replace with '$'
idxs = itertools.combinations(range(len(SearchL)),n)
# for each combination `idx` in idxs, replace str[idx] with '$':
for idx in idxs:
str = SearchL[:] # make a copy
for i in idx:
str[i]='$'
List.append( ''.join(str) ) # convert back to string
return List
让我们来看看它是如何工作的:
Search
字符串转换为列表,以便迭代,创建空List
以保存结果。 idxs = itertools.combinations(range(len(SearchL)),n)
说“在集合[0,1,2,3,...,length-of-search-string -1]
中查找长度为n的所有子集。
试试
idxs = itertools.combinations(range(5),4)
for idx in idxs:
print idx
看看我的意思。
idxs
的每个元素都是从0到n
的{{1}}索引元组(例如len(SearchL)-1
。将(0,1,2,4)
的第i个字符替换为元组中每个SearchL
的'$'。i
。举个例子:
List