2012-01-02 14 views
6

Objetivo: convertir binario a cadenabinario a cadena, mejor que un diccionario?

Ejemplo: 0111010001100101011100110111010001100011011011110110010001100101 -> testCode (sin espacio)

utilizo un diccionario y mi función, i buscar una manera mejor y más eficiente

from textwrap import wrap 

DICO = {'\x00': '00', '\x04': '0100', '\x08': '01000', '\x0c': '01100', 
'\x10': '010000', '\x14': '010100', '\x18': '011000', '\x1c': '011100', 
' ': '0100000', '$': '0100100', '(': '0101000', ',': '0101100', '0': '0110000', 
'4': '0110100', '8': '0111000', '<': '0111100', '@': '01000000', 
'D': '01000100', 'H': '01001000', 'L': '01001100', 'P': '01010000', 
'T': '01010100', 'X': '01011000', '\\': '01011100', '`': '01100000', 
'd': '01100100', 'h': '01101000', 'l': '01101100', 'p': '01110000', 
't': '01110100', 'x': '01111000', '|': '01111100', '\x03': '011', 
'\x07': '0111', '\x0b': '01011', '\x0f': '01111', '\x13': '010011', 
'\x17': '010111', '\x1b': '011011', '\x1f': '011111', '#': '0100011', 
"'": '0100111', '+': '0101011', '/': '0101111', '3': '0110011', '7': '0110111', 
';': '0111011', '?': '0111111', 'C': '01000011', 'G': '01000111', 
'K': '01001011', 'O': '01001111', 'S': '01010011', 'W': '01010111', 
'[': '01011011', '_': '01011111', 'c': '01100011', 'g': '01100111', 
'k': '01101011', 'o': '01101111', 's': '01110011', 'w': '01110111', 
'{': '01111011', '\x7f': '01111111', '\x02': '010', '\x06': '0110', 
'\n': '01010', '\x0e': '01110', '\x12': '010010', '\x16': '010110', 
'\x1a': '011010', '\x1e': '011110', '"': '0100010', '&': '0100110', 
'*': '0101010', '.': '0101110', '2': '0110010', '6': '0110110', ':': '0111010', 
'>': '0111110', 'B': '01000010', 'F': '01000110', 'J': '01001010', 
'N': '01001110', 'R': '01010010', 'V': '01010110', 'Z': '01011010', 
'^': '01011110', 'b': '01100010', 'f': '01100110', 'j': '01101010', 
'n': '01101110', 'r': '01110010', 'v': '01110110', 'z': '01111010', 
'~': '01111110', '\x01': '01', '\x05': '0101', '\t': '01001', '\r': '01101', 
'\x11': '010001', '\x15': '010101', '\x19': '011001', '\x1d': '011101', 
'!': '0100001', '%': '0100101', ')': '0101001', '-': '0101101', 
'1': '0110001', '5': '0110101', '9': '0111001', '=': '0111101', 
'A': '01000001', 'E': '01000101', 'I': '01001001', 'M': '01001101', 
'Q': '01010001', 'U': '01010101', 'Y': '01011001', ']': '01011101', 
'a': '01100001', 'e': '01100101', 'i': '01101001', 'm': '01101101', 
'q': '01110001', 'u': '01110101', 'y': '01111001', '}': '01111101'} 

def decrypt(binary): 
    """Function to convert binary into string""" 
    binary = wrap(binary, 8) 
    ch = '' 
    for b in binary: 
     for i, j in DICO.items(): 
      if j == b: 
       ch += i 
    return ch 

de agradecimiento por adelantado,

+1

¿Qué es exactamente lo que quiere mejorar? ¿Complejidad espacial o temporal?¿Qué algoritmo usas actualmente, acabas de dividir la cadena? – RedX

+6

¿Cómo se decide si la secuencia '010001' es' 0100' (= '\ x04') seguida del inicio de una secuencia' 01', o es el comienzo de un carácter de marca de almohadilla, '0100011'? Si todos los caracteres tienen el mismo número de bits (presumiblemente 7 u 8 bits), ¿por qué no se escribe el código '\ x00' como' 00000000' en su ejemplo, pero '00'? Los datos de ejemplo dejan mucho espacio para la interpretación ... – hochl

+0

@Redx, gracias por su respuesta, busco un mejor momento de ejecución, si no guardo mi código – Fred

Respuesta

2

¿Usted intentó

def decrypt(binary): 
    """Function to convert binary into string""" 
    return ''.join((chr(int(p, 2)) for p in grouper(8,binary,''))) 

donde mero está tomada de aquí http://docs.python.org/library/itertools.html#recipes

o

def decrypt2(binary): 
    """Function to convert binary into string""" 
    return ''.join((DICO_INVERTED[p] for p in grouper(8,binary,''))) 

que evita crear lista temporal

EDITAR como me dijeron que era la respuesta "correcta", debo confesar que utilicé las otras respuestas. El punto aquí es no utilizar la lista de generadores, pero la expresión del generador y los iteradores

+0

¡Muy bien! exceptionnel, gracias – Fred

+0

¿cuál probaste el que tiene el diccionario o el otro? –

+0

un promedio de 14 segundos, su propuesta da 0,006 segundos, puntaje estupendo, muchas gracias – Fred

14
''.join([ chr(int(p, 2)) for p in wrap(binstr, 8) ]) 

Qué hace esto: wrap primero divide la cuerda en trozos de 8. Luego, repito a través de cada uno y lo convierto en un número entero (base 2). Cada uno de esos enteros convertidos ahora se cubre a un personaje con chr. Finalmente lo envuelvo con un ''.join para aplastarlo todo.

un poco más de un desglose de cada paso de la chr(int(p, 2)):

>>> int('01101010', 2) 
106 
>>> chr(106) 
'j' 

para que se ajuste a su modelo anterior:

def decrypt(binary): 
    """Function to convert binary into string""" 
    binary = wrap(binary, 8) 
    ch = '' 
    for b in binary: 
     ch += chr(int(b, 2)) 
    return ch 

o

def decrypt(binary): 
    """Function to convert binary into string""" 
    return ''.join([ chr(int(p, 2)) for p in wrap(binary, 8) ]) 

Este es Definitivamente más rápido ya que solo está haciendo los cálculos en su lugar, no iterando a través del diccionario una y otra vez. Además, es más legible.

+0

por el momento, ¡es equivalente! – Fred

+0

¿Qué tan grande es tu cuerda? Podría ser que el 'wrap' esté tomando la mayoría del tiempo y no hay mucho que puedas hacer al respecto. De cualquier manera, esto es aún más legible que esa monstruosidad de un diccionario. –

+0

No sé para envolver pero el diccionario tiene una longitud de 5000 -> 1,94 segundos y tu código -> 3,45 segundos – Fred

3

Si la velocidad de ejecución es lo más importante para usted, ¿por qué no invierte los roles de las teclas y los valores en su dict? (Si también necesita el dict actual, podría crear una versión invertida como esta {v:k for k, v in DICO.items()})

Ahora, encuentra directamente la traducción buscada por clave en lugar de recorrer todo el diccionario.

Su nueva función se vería así:

def decrypt2(binary): 
    """Function to convert binary into string""" 
    binary = wrap(binary, 8) 
    ch = '' 
    for b in binary: 
     if b in DICO_INVERTED: 
      ch += DICO_INVERTED[b] 
    return ch 

Dependiendo del tamaño de su cadena binaria, que podría ganar algo de tiempo al cambiar la forma de construir su salida de cuerdas (ver Efficient String Concatenation in Python o performance tips - string concatenation). Usar join parece prometedor. Me gustaría darle una oportunidad: ''.join(DICO_INVERTED.get(b, '') for b in binary)

+1

También sugiero crear el dict con código en lugar de tipearlo. –

+0

@orangeoctopus, no escribo el dict;) – Fred

+0

@gecco, es más eficiente, ¡gracias! – Fred

Cuestiones relacionadas