【问题标题】:Convert ascii encoding to int and back again in python (quickly)在 python 中将 ascii 编码转换为 int 并再次返回(快速)
【发布时间】:2010-09-27 16:20:59
【问题描述】:

我有一种文件格式(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 版本中更好地编写这个代码,都会很有帮助。

谢谢,

肖恩

【问题讨论】:

  • 尝试将[] 替换为() 以使用生成器,而不是创建和丢弃列表。我怀疑它会产生巨大的变化,但它应该会产生一些影响。
  • 将 [] 重新替换为 (),() 对于任何最近的 python 都是多余的
  • 好主意,但我相信字符串连接需要一个列表,所以我认为这不会直接起作用。
  • 嗯,使用 Python 2.6.1:".".join(x for x in ["1", "2", "3"]) -> '1.2.3'
  • 我很愚蠢。我在 cython 下运行了生成器——那里不支持。 Python 2.6.2 使用生成器版本慢了 20%。

标签: python algorithm performance cython


【解决方案1】:

如果您查看 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)

【讨论】:

  • 谢谢,迈克。在与上述相同的机器上,这是一个极快的 0.1 秒,对于我的目的来说已经足够快了。我会坚持使用上面列出的 phred64ToStdqual4()....
猜你喜欢
  • 2011-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2014-11-13
  • 2021-02-25
相关资源
最近更新 更多