Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 字符串操作似乎效率低下_Python - Fatal编程技术网

Python 字符串操作似乎效率低下

Python 字符串操作似乎效率低下,python,Python,我觉得我的代码效率太低了。我猜这与使用字符串有关,尽管我不确定。代码如下: genome = FASTAdata[1] genomeLength = len(genome); # Hash table holding all the k-mers we will come across kmers = dict() # We go through all the possible k-mers by index for outer in range (0, genomeLength-1):

我觉得我的代码效率太低了。我猜这与使用字符串有关,尽管我不确定。代码如下:

genome = FASTAdata[1]
genomeLength = len(genome);

# Hash table holding all the k-mers we will come across
kmers = dict()

# We go through all the possible k-mers by index
for outer in range (0, genomeLength-1):
    for inner in range (outer+2, outer+22):
        substring = genome[outer:inner]
        if substring in kmers:              # if we already have this substring on record, increase its value (count of num of appearances) by 1
            kmers[substring] += 1
        else:
            kmers[substring] = 1            # otherwise record that it's here once
这是搜索所有长度不超过20的子字符串。现在,这段代码似乎要花很长时间,而且永远不会终止,所以这里肯定有问题。在字符串上使用[:]会导致巨大的开销吗?如果是,我可以用什么来代替它


为了清楚起见,所讨论的文件将近200mb,非常大。

我建议使用动态编程算法。问题是,对于所有未找到的
内部
字符串,您将使用附加字符再次搜索这些字符串,因此当然也不会找到这些字符串。我脑子里没有一个特定的算法,但这肯定是动态规划的一个例子,在动态规划中,您可以记住您已经搜索过的内容。作为一个非常糟糕的例子,请记住所有长度为1,2,3,。。。在下一次迭代中,如果字符串更长,则永远不要扩展这些基

您应该使用以避免创建子字符串,因为
[:]
随后将返回“视图”而不是副本,但必须使用Python 3.3或更高版本(在此之前,它们是不可散列的)

此外,a将简化您的代码

from collections import Counter

genome = memoryview("abcdefghijkrhirejtvejtijvioecjtiovjitrejabababcd".encode('ascii'))
genomeLength = len(genome)

minlen, maxlen = 2, 22

def fragments():
    for start in range (0, genomeLength-minlen):
        for finish in range (start+minlen, start+maxlen):
            if finish <= genomeLength:
                yield genome[start:finish]

count = Counter(fragments())
for (mv, n) in count.most_common(3):
    print(n, mv.tobytes())
在我的笔记本电脑上,一个1000000字节的随机数组需要45秒,但2000000会导致交换(超过8GB的内存使用)。然而,由于片段的大小很小,您可以很容易地将问题分解成百万长的子序列,然后在最后合并结果(只是要小心重叠)。如果运气好的话,200MB阵列的总运行时间约为3小时


PS为了清楚起见,通过“在末尾合并结果”,我假设您只需要为每个1M子序列保存最常用的结果,例如,将它们写入文件。您不能将计数器保留在内存中-这就是使用8GB的原因。如果你有成千上万次出现的片段,这很好,但显然对较小的数字不起作用(例如,你可能在200 1M子序列的每个子序列中只看到一个片段,因此永远不会保存它)。换句话说,结果将是不完整的下限,尤其是在较低的频率下(只有在每个子序列中找到并记录了片段时,值才是完整的)。如果您需要一个精确的结果,这是不合适的。

您能分享一些输入文件中的基因组字符串样本吗?如果
genomeLength
是~200M,那么您有~40000000000次迭代。那不是一个巨蟒擅长的政权。(PS:我认为你的代码有一个错误:<代码>子字符串< /代码>可以比<代码>内外字符长,所以你可以多次对同一个字符切片进行计数。)用一个很短的文件测试它是否有帮助,看看它是否产生想要的结果。考虑使用<代码> Debug(int)而不是简单的
dict
,那么您可以在不使用
的情况下执行:
kmers[substring]+=1
如果
s,它还可以避免双重查找。您应该将
范围
调用更改为
范围
调用,这样您就可以构造迭代器而不是完整的列表。
4 b'ab'
3 b'jt'
3 b'ej'