2010-09-27 39 views
6

Tengo un formato de archivo (formato fastq) que codifica una cadena de enteros como una cadena donde cada entero está representado por un código ascii con un desplazamiento. Desafortunadamente, hay dos codificaciones de uso común, una con un desplazamiento de 33 y la otra con un desplazamiento de 64. Normalmente tengo varios 100 millones de cadenas de longitud 80-150 para convertir de una compensación a la otra. El código más simple que podía llegar a hacer para este tipo de cosas es:Convertir codificación ascii a int y viceversa en python (rápidamente)

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

Esto funciona bien, pero no es especialmente rápido. Para 1 millón de cuerdas, lleva unos 4 segundos en mi máquina. Si cambio a usar un par de dicts para hacer la traducción, puedo bajar esto a aproximadamente 2 segundos.

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])) 

Si corro a ciegas bajo cython, lo bajo a menos de 1 segundo.
Parece que en el nivel C, esto es simplemente un molde para int, restar, y luego lanzar a char. No he escrito esto, pero supongo que es bastante más rápido. Cualquier sugerencia que incluya cómo codificar mejor esto en python o incluso una versión de cython para hacer esto sería bastante útil.

Gracias,

Sean

+0

Intente reemplazar '[] 'con'() 'para usar generadores en lugar de crear y descartar listas. Dudo que hará una gran diferencia, pero debería hacer algo. – RichieHindle

+0

Reemplazando [] con(), the() son redundantes con cualquier pitón reciente – pixelbeat

+0

Buena idea, pero la unión de cadenas necesita una lista, creo, por lo que no funcionará directamente, no creo. – seandavi

Respuesta

4

Si nos fijamos en el código para urllib.quote, hay algo que es similar a lo que está haciendo. Parece que:

_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)) 

Tenga en cuenta que la función anterior funciona en el caso de las asignaciones no son la misma longitud (en urllib.quote, usted tiene que tomar '%' -> '% 25'

. pero, en realidad, ya que cada traducción es la misma longitud, Python tiene una función que hace precisamente esto muy rápidamente:. maketrans y translate probablemente no va a conseguir mucho más rápido que:

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

Gracias, Mike. Es un extremadamente rápido 0.1 segundos en la misma máquina que la anterior y será lo suficientemente rápido para mis propósitos. Me quedaré con phred64ToStdqual4() como se menciona arriba .... – seandavi

Cuestiones relacionadas