separar - Invierta una cadena en Python dos caracteres a la vez(orden de bytes de red)
range al reves python (12)
Digamos que tienes esta cadena:
ABCDEFGH
Y quieres revertirlo para que se convierta en:
GHEFCDAB
¿Cuál sería la solución más eficiente / pitónica? He intentado algunas cosas diferentes pero todas se ven horribles ...
¡Gracias por adelantado!
Actualización :
En caso de que alguien esté interesado, esto no fue para la tarea. Tenía un script que procesaba datos de una captura de red y los devolvía como una cadena de bytes hexadecimales. El problema era que los datos todavía estaban en orden de la red. Debido a la forma en que se escribió la aplicación, no quería volver atrás y tratar de usar, por ejemplo, socket.htons, solo quería invertir la cadena.
Desafortunadamente, mis intentos parecían tan horribles, sabía que debía haber una mejor manera (una solución más pitónica), de ahí mi pregunta aquí.
Aquí hay una forma general. El tamaño de la agrupación se puede cambiar fácilmente a un número diferente de caracteres a la vez. La longitud de la cadena debe ser un múltiplo exacto del tamaño de agrupación
>>> "".join(map("".join, reversed(zip(*[iter("ABCDEFGH")]*2))))
''GHEFCDAB''
(Esto es Python 2, no funcionará en 3)
Esto se parece a la tarea. Así que aquí hay un enfoque muy poco ortodoxo que podría encontrar interesante:
>>> s = "ABCDEFGH"
>>> ''''.join([s[::2][::-1][i]+s[::-2][i] for i in range(len(s[::2]))])
''GHEFCDAB''
¡Buena suerte!
Mi amigo Rob señaló una hermosa solución recursiva:
def f(s):
return "" if not s else f(s[2:]) + s[:2]
Muchas maneras divertidas de hacer esto
>>> s="ABCDEFGH"
>>> "".join(map(str.__add__, s[-2::-2] ,s[-1::-2]))
''GHEFCDAB''
Puedes usar esto, pero no le digas a nadie que escribí este código :-)
import struct
def pair_reverse(s):
n = len(s) / 2
fmt = ''%dh'' % n
return struct.pack(fmt, *reversed(struct.unpack(fmt, s)))
pair_reverse(''ABCDEFGH'')
Si alguien está interesado, este es el momento para todas * las respuestas.
EDITAR (se había equivocado la primera vez):
import timeit
import struct
string = "ABCDEFGH"
# Expected resutlt => GHEFCDAB
def rev(a):
new = ""
for x in range(-1, -len(a), -2):
new += a[x-1] + a[x]
return new
def rev2(a):
return "".join(reversed([a[i:i+2] for i in range(0, len(a), 2)]))
def rev3(a):
return "".join(map(str.__add__, a[-2::-2] ,a[-1::-2]))
def rev4(a):
return "".join(map("".join, reversed(zip(*[iter(a)]*2))))
def rev5(a):
n = len(a) / 2
fmt = ''%dh'' % n
return struct.pack(fmt, *reversed(struct.unpack(fmt, a)))
def rev6(a):
return "".join([a[x:x+2] for x in range(0,len(a),2)][::-1])
print "Greg Hewgill %f" %timeit.Timer("rev2(string)", "from __main__ import rev2, string").timeit(100000)
print "gnibbler %f" %timeit.Timer("rev3(string)", "from __main__ import rev3, string").timeit(100000)
print "gnibbler second %f" %timeit.Timer("rev4(string)", "from __main__ import rev4, string").timeit(100000)
print "Alok %f" %timeit.Timer("rev5(string)", "from __main__ import rev5, struct, string").timeit(100000)
print "elliot42 %f" %timeit.Timer("rev6(string)", "from __main__ import rev6, struct, string").timeit(100000)
print "me %f" %timeit.Timer("rev(string)", "from __main__ import rev, string").timeit(100000)
resultados para string = "ABCDEFGH"
:
Greg Hewgill 0.853000
gnibbler 0.428000
gnibbler second 0.707000
Alok 0.763000
elliot42 0.237000
me 0.200000
resultados para string = "ABCDEFGH"*5
:
Greg Hewgill 2.246000
gnibbler 0.811000
gnibbler second 1.205000
Alok 0.972000
elliot42 0.594000
me 0.584000
resultados para string = "ABCDEFGH"*10
:
Greg Hewgill 2.058000
gnibbler 1.178000
gnibbler second 1.926000
Alok 1.210000
elliot42 0.935000
me 1.082000
resultados para string = "ABCDEFGH"*100
:
Greg Hewgill 9.762000
gnibbler 9.134000
gnibbler second 14.782000
Alok 5.775000
elliot42 7.351000
me 18.140000
* Lo siento, @Lacrymology no pudo hacer que tu trabajo!
Una forma concisa de hacer esto es:
"".join(reversed([a[i:i+2] for i in range(0, len(a), 2)]))
Esto funciona dividiendo primero la cadena en pares:
>>> [a[i:i+2] for i in range(0, len(a), 2)]
[''AB'', ''CD'', ''EF'', ''GH'']
luego invirtiendo eso, y finalmente concatenando el resultado de nuevo juntos.
Y otra manera más:
a = "ABCDEFGH"
new = ""
for x in range(-1, -len(a), -2):
new += a[x-1] + a[x]
print new
solo un tiro
st = "ABCDEFGH"
s = [st[2*n:2*n+1] for n in range(len(st)/2)]
return s[::-1].join('''')
esto supone que len (st) es par, de lo contrario, cámbielo a rango (len (st) / 2 + 1) y estoy seguro de que hay una mejor manera de dividir en dos.
Si su python se queja de s [:: - 1], puede usar reversa (s)
y otro se pone ...
>>> rev = "ABCDEFGH"[::-1]
>>> ''''.join([''''.join(el) for el in zip(rev[1::2], rev[0::2])])
''GHEFCDAB''
>>> import array
>>> s="abcdef"
>>> a=array.array(''H'',s)
>>> a.byteswap()
>>> a.tostring()
''badcfe''
Para finalizar, utilice a.reverse () en lugar de a.byteswap () si desea intercambiar el orden de los elementos en lugar del orden de bytes.
Me tomé la libertad de editar un poco el guión de referencia de Trufa. El script modificado generó una gráfica gráfica que mostraba una escala aproximadamente lineal para todas las funciones.
st = "ABCDEFGH"
"".join([st[x:x+2] for x in range(0,len(st),2)][::-1])
EDIT: Maldiciones, al parecer, 27 minutos más lento que otro cartel. Pero me gusta más la notación de corte inverso.
Un poco más de información sobre el corte inverso aquí: "" .join (reversed (val)) vs val [:: - 1] ... ¿cuál es pythonic?