将ascii编码转换为int并在python中再次返回(快速)

时间:2010-09-27 16:21:00

标签: python algorithm performance cython

我有一种文件格式(fastq格式),它将一个整数字符串编码为一个字符串,其中每个整数由带有偏移量的ascii代码表示。不幸的是,有两种常用的编码,一种偏移量为33,另一种偏移量为64.我通常有几个1亿个字符串,长度为80-150,可以从一个偏移量转换到另一个偏移量。我可以用来做这类事情的最简单的代码是:

def phred64ToStdqual(qualin):
    return(''.join([chr(ord(x)-31) for x in qualin]))

这很好用,但速度不是很快。对于100万个字符串,我的机器大约需要4秒钟。如果我改用使用几个dicts进行翻译,我可以将其缩短到大约2秒。

ctoi = {}
itoc = {}
for i in xrange(127):
    itoc[i]=chr(i)
    ctoi[chr(i)]=i

def phred64ToStdqual2(qualin):
    return(''.join([itoc[ctoi[x]-31] for x in qualin]))

如果我盲目地在cython下运行,我会把它降到1秒以下 看起来像在C级,这只是一个转换为int,减去,然后转换为char。我没有写这篇文章,但我猜它速度要快得多。任何提示,包括如何在python甚至cython版本中更好地编写代码都会非常有用。

谢谢,

肖恩

1 个答案:

答案 0 :(得分:4)

如果你看一下urllib.quote的代码,就会有类似于你正在做的事情。它看起来像:

_map = {}
def phred64ToStdqual2(qualin):
    if not _map:
        for i in range(31, 127):
            _map[chr(i)] = chr(i - 31)
    return ''.join(map(_map.__getitem__, qualin))

请注意,上述函数适用于映射长度不同的情况(在urllib.quote中,您必须使用'%' - >'%25'。

但实际上,由于每个转换的长度都相同,因此python有一个能够非常快速地执行此操作的函数:maketranstranslate。你可能不会比以下更快:

import string
_trans = None
def phred64ToStdqual4(qualin):
    global _trans
    if not _trans:
        _trans = string.maketrans(''.join(chr(i) for i in range(31, 127)), ''.join(chr(i) for i in range(127 - 31)))
    return qualin.translate(_trans)