1

我编写了这个野蛮的脚本来创建字符串的排列,该字符串在字符串中所有可能的位置组合中包含 n(最多 n = 4)$。我最终会.replace('$','(\\w)')用于 dna 搜索序列中的不匹配。由于我编写脚本的方式,某些排列少于请求的 $ 数量。然后我编写了一个脚本来删除它们,但它似乎并不有效,并且每次我运行删除脚本时,它都会删除更多不需要的排列。在下面粘贴的代码中,您将看到我使用一个包含 4 个不匹配的简单序列来测试该函数。然后我运行一系列删除脚本,计算每次删除了多少表达式……根据我的经验,删除所有通配符 $ 少于 4 个的表达式大约需要 8 次。我对此有几个问题:

  1. 是否有用于搜索“n”不匹配的内置函数?甚至在 biopython 中?到目前为止,我已经看到了 Paul_McGuire_regex 函数:
    Search for string allowed for one mismatch in any location of the string
    这似乎只会产生 1 个不匹配。我必须承认,我并不完全理解该页面上剩余功能中的所有代码,因为我是一个非常新的编码器。

  2. 由于我认为这对我来说是一个很好的练习,有没有更好的方法来编写整个脚本?...我可以根据需要多次迭代 Paul_McGuire_regex 函数吗?

  3. 最让我困惑的是,为什么删除脚本第一次不能 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))
4

1 回答 1

3

我们可以通过回答问题 1 来取消问题 2 和 3,但是理解问题 3 很重要,所以我将首先这样做,然后展示如何完全避免它:

问题 3

至于问题3,这是因为当您在python中循环一个列表并在循环中对其进行更改时,您循环的列表会发生变化。

来自关于控制流的python文档(用于语句部分)

在循环中修改被迭代的序列是不安全的(这只会发生在可变序列类型上,例如列表)。

假设您的列表是[a,b,c,d],然后使用for el in List. 说el是目前a,你做List.remove(el)

现在,您的清单是[b,c,d]. 但是,迭代器指向列表中的第二个元素(因为它完成了第一个元素),即 now 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,所以我们没有跳过任何内容。

基本上,这避免了修改您尚未迭代的列表位。

问题 1 和 2

如果我正确理解您的问题,您基本上想nm位置中选择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

让我们看看这是如何工作的:

  1. Search字符串转换为列表,以便对其进行迭代,创建空List以保存结果。
  2. idxs = itertools.combinations(range(len(SearchL)),n)说“在集合中找到所有长度为 n 的子集[0,1,2,3,...,length-of-search-string -1]。试试

    idxs = itertools.combinations(range(5),4)
    for idx in idxs: 
        print idx
    

    看看我的意思。

  3. 的每个元素idxs是一个从 0 到(例如. 的n索引的元组。将元组中的每个元素替换为 '$'的第 i 个字符。len(SearchL)-1(0,1,2,4)SearchLi
  4. 将结果转换回字符串并将其添加到List.

举个例子:

Mismatch('abcde',3)
['$$$de', '$$c$e', '$$cd$', '$b$$e', '$b$d$', '$bc$$', 'a$$$e', 'a$$d$', 'a$c$$', 'ab$$$']
Mismatch('abcde',4) # note, the code you had made lots of duplicates.
['$$$$e', '$$$d$', '$$c$$', '$b$$$', 'a$$$$'] 
于 2011-12-14T23:41:43.247 回答