¿Cuál es la forma más pitónica de unir dos cuerdas?
Por ejemplo:
Entrada:
u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'
Salida:
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
python
string
python-2.7
python-3.x
Brandon Deo
fuente
fuente
Respuestas:
Para mí, la forma más pitónica * es la siguiente, que prácticamente hace lo mismo pero usa el
+
operador para concatenar los caracteres individuales en cada cadena:También es más rápido que usar dos
join()
llamadas:Existen enfoques más rápidos, pero a menudo confunden el código.
Nota: Si las dos cadenas de entrada no tienen la misma longitud, la más larga se truncará cuando
zip
deje de iterar al final de la cadena más corta. En este caso, en lugar dezip
uno, debería usarzip_longest
(izip_longest
en Python 2) delitertools
módulo para asegurarse de que ambas cadenas se agoten por completo.* Para tomar una cita del Zen de Python : la legibilidad cuenta .
Pythonic = legibilidad para mí;
i + j
se analiza visualmente más fácilmente, al menos para mis ojos.fuente
"".join([i + j for i, j in zip(l1, l2)])
y definitivamente será el más rápido"".join(map("".join, zip(l1, l2)))
es incluso más rápido, aunque no necesariamente más pitónico.Alternativa más rápida
De otra manera:
Salida:
Velocidad
Parece que es más rápido:
que la solución más rápida hasta ahora:
También para las cuerdas más grandes:
Python 3.5.1.
Variación para cuerdas con diferentes longitudes
El más corto determina la longitud (
zip()
equivalente)Salida:
Uno más largo determina la longitud (
itertools.zip_longest(fillvalue='')
equivalente)Salida:
fuente
Con
join()
yzip()
.fuente
''.join(itertools.chain.from_iterable(zip(u, l)))
zip
detiene cuando la lista más corta se ha iterado por completo.itertools.zip_longest
se puede utilizar si se convierte en un problema.En Python 2, con mucho, la forma más rápida de hacer las cosas, a ~ 3 veces la velocidad de corte de la lista para cadenas pequeñas y ~ 30x para cadenas largas, es
Sin embargo, esto no funcionaría en Python 3. Podrías implementar algo como
pero para entonces ya ha perdido las ganancias sobre la división de listas para cadenas pequeñas (sigue siendo 20 veces la velocidad para cadenas largas) y esto ni siquiera funciona para caracteres que no son ASCII todavía.
FWIW, si está haciendo esto en cadenas masivas y necesita cada ciclo, y por alguna razón tiene que usar cadenas de Python ... así es como se hace:
La carcasa especial, el caso común de tipos más pequeños, también ayudará. FWIW, esto es solo 3 veces la velocidad de corte de listas para cadenas largas y un factor de 4 a 5 más lento para cadenas pequeñas.
De cualquier manera, prefiero las
join
soluciones, pero como los tiempos se mencionaron en otra parte, pensé que también podría unirme.fuente
Si desea la forma más rápida, puede combinar itertools con
operator.add
:Pero combinando
izip
ychain.from_iterable
es más rápido de nuevoTambién hay una diferencia sustancial entre
chain(*
ychain.from_iterable(...
.No existe un generador con combinación, pasar uno siempre será más lento, ya que Python primero creará una lista utilizando el contenido porque hace dos pasadas sobre los datos, una para determinar el tamaño necesario y otra para hacer realmente la unión que no sería posible usando un generador:
unirse.h :
Además, si tiene cadenas de diferente longitud y no desea perder datos, puede usar izip_longest :
Para python 3 se llama
zip_longest
Pero para python2, la sugerencia de veedrac es, con mucho, la más rápida:
fuente
list
?? es innecesario"".join(list(...))
dame 6.715280318699769 y timeit the"".join(starmap(...))
dame 6.46332361384313"".join(list(starmap(add, izip(l1,l2))))
es más lento que"".join(starmap(add, izip(l1,l2)))
. Ejecuto la prueba en mi máquina en python 2.7.11 y en python 3.5.1 incluso en la consola virtual de www.python.org con python 3.4.3 y todos dicen lo mismo y lo ejecuto un par de veces y siempre el mismoTambién puede hacer esto usando
map
yoperator.add
:Salida :
Lo que hace el mapa es que toma todos los elementos del primer iterable
u
y los primeros elementos del segundo iterablel
y aplica la función proporcionada como primer argumentoadd
. Entonces únete solo se une a ellos.fuente
La respuesta de Jim es excelente, pero esta es mi opción favorita, si no le importan un par de importaciones:
fuente
Muchas de estas sugerencias asumen que las cadenas tienen la misma longitud. Tal vez eso cubra todos los casos de uso razonables, pero al menos a mí me parece que es posible que también desee acomodar cadenas de diferentes longitudes. ¿O soy el único que piensa que la malla debería funcionar un poco así:
Una forma de hacerlo sería la siguiente:
fuente
Me gusta usar dos
for
s, los nombres de las variables pueden dar una pista / recordatorio de lo que está sucediendo:fuente
Solo para agregar otro enfoque más básico:
fuente
Se siente un poco poco pitónico no considerar la respuesta de comprensión de doble lista aquí, para manejar n cadena con O (1) esfuerzo:
donde
all_strings
es una lista de las cadenas que desea intercalar. En tu casoall_strings = [u, l]
,. Un ejemplo de uso completo se vería así:Como muchas respuestas, ¿más rápido? Probablemente no, pero simple y flexible. Además, sin demasiada complejidad adicional, esto es un poco más rápido que la respuesta aceptada (en general, la adición de cadenas es un poco lenta en Python):
fuente
Potencialmente más rápido y más corto que la solución líder actual:
La estrategia en cuanto a velocidad es hacer todo lo posible en el nivel C. La misma solución zip_longest () para cadenas desiguales y saldría del mismo módulo que chain (), ¡así que no puedo marcarme demasiados puntos allí!
Otras soluciones que se me ocurrieron en el camino:
fuente
Podrías usar 1
iteration_utilities.roundrobin
o la
ManyIterables
clase del mismo paquete:1 Se trata de una biblioteca de terceros que he escrito:
iteration_utilities
.fuente
Usaría zip () para obtener una manera fácil y legible:
fuente