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

sea*_*avi 6 python algorithm performance cython

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

def phred64ToStdqual(qualin):
    return(''.join([chr(ord(x)-31) for x in qualin]))
Run Code Online (Sandbox Code Playgroud)

这很好用,但速度不是很快.对于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]))
Run Code Online (Sandbox Code Playgroud)

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

谢谢,

肖恩

Mik*_*iak 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))
Run Code Online (Sandbox Code Playgroud)

请注意,上述函数在映射长度不同的情况下起作用(在 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)
Run Code Online (Sandbox Code Playgroud)