Unir pares de elementos de una lista

82

Sé que se puede unir una lista para hacer una cadena larga como en:

x = ['a', 'b', 'c', 'd']
print ''.join(x)

Obviamente, esto daría como resultado:

'abcd'

Sin embargo, lo que estoy tratando de hacer es simplemente unir la primera y la segunda cadena de la lista, luego unir la tercera y la cuarta y así sucesivamente. En resumen, a partir del ejemplo anterior, obtenga una salida de:

['ab', 'cd']

¿Existe alguna forma sencilla de hacer esto? Probablemente también debería mencionar que las longitudes de las cadenas en la lista serán impredecibles, al igual que el número de cadenas dentro de la lista, aunque la cantidad de cadenas siempre será par. Entonces, la lista original también podría ser:

['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'] 
Juan
fuente
"Probablemente también debería mencionar que las longitudes de las cadenas de la lista serán impredecibles" . Entonces, ¿importa la longitud? Es decir, ¿solo desea unir cada par de elementos de la lista, o realmente desea ver el contenido y unirse siempre que el elemento resultante permanezca por debajo de algún límite de longitud especial?
empuje
simplemente únase a cada par, solo pensé que no saber el número de pares podría ser un problema
John

Respuestas:

75

Puede usar la notación de corte con pasos:

>>> x = "abcdefghijklm"
>>> x[0::2] #0. 2. 4...
'acegikm'
>>> x[1::2] #1. 3. 5 ..
'bdfhjl'
>>> [i+j for i,j in zip(x[::2], x[1::2])] # zip makes (0,1),(2,3) ...
['ab', 'cd', 'ef', 'gh', 'ij', 'kl']

La misma lógica se aplica también a las listas. La longitud de la cuerda no importa, porque simplemente está agregando dos cuerdas.

utdemir
fuente
1
No hay duda de que la respuesta de kevpie es mucho mejor. En este, x[:::2]crea un objeto, x[1::2]crea otro objeto, probablemente estas creaciones se basan en el cálculo de índices bajo el capó, y es necesaria una llamada a una función con estos dos objetos pasados ​​como argumentos antes de poder obtener los sucesivos pares de elementos que debe concatenarse. Mientras que en la respuesta de kevpie, solo existe la creación de un iterador y luego la iteración salta de un elemento a otro de la lista intacta sin tener que ocuparse de los índices, y eso es mucho más pitónico.
eyquem
@eyquem, usando en itertools.islicelugar de [], elimina los objetos intermedios. Pero dado que ambas respuestas funcionan en las mismas condiciones y devuelven lo mismo, ambas son correctas. Y me zip(i[::2], i[1::2])parece tan dulce, entonces, ¿por qué no? :)
utdemir
Esto solo funciona en secuencias , mientras que la respuesta de @ kevpie es más general y funciona en cualquier iterable .
Kos
37

Utilice un iterador.

Comprensión de listas:

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> [c+next(si, '') for c in si]
['abcde', 'fghijklmn', 'opqr']
  • Muy eficiente para el uso de memoria.
  • Exactamente un recorrido de s

Expresión del generador:

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> pair_iter = (c+next(si, '') for c in si)
>>> pair_iter # can be used in a for loop
<generator object at 0x4ccaa8>
>>> list(pair_iter) 
['abcde', 'fghijklmn', 'opqr']
  • usar como iterador

Usando map, str .__ add__, iter

>>> si = iter(['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'])
>>> map(str.__add__, si, si)
['abcde', 'fghijklmn', 'opqr']

siguiente (iterador [, predeterminado]) está disponible a partir de Python 2.6

kevpie
fuente
2
De lejos, la mejor respuesta. Vea mi comentario a la respuesta de utdemir.
eyquem
4

solo para ser pitonico :-)

>>> x = ['a1sd','23df','aaa','ccc','rrrr', 'ssss', 'e', '']
>>> [x[i] + x[i+1] for i in range(0,len(x),2)]
['a1sd23df', 'aaaccc', 'rrrrssss', 'e']

en caso de que desee alarmarse si la longitud de la lista es extraña, puede intentar:

[x[i] + x[i+1] if not len(x) %2 else 'odd index' for i in range(0,len(x),2)]

La mejor de las suertes

Mahmoh
fuente
2

Sin construir listas temporales:

>>> import itertools
>>> s = 'abcdefgh'
>>> si = iter(s)
>>> [''.join(each) for each in itertools.izip(si, si)]
['ab', 'cd', 'ef', 'gh']

o:

>>> import itertools
>>> s = 'abcdefgh'
>>> si = iter(s)
>>> map(''.join, itertools.izip(si, si))
['ab', 'cd', 'ef', 'gh']
pillmuncher
fuente
Bien, pero teniendo en cuenta que mi código me deja comenzando con la lista original de todos modos, creo que optaré por utdmr ... aunque gracias
John
1
>>> lst =  ['abcd', 'e', 'fg', 'hijklmn', 'opq', 'r'] 
>>> print [lst[2*i]+lst[2*i+1] for i in range(len(lst)/2)]
['abcde', 'fghijklmn', 'opqr']
Andreas Jung
fuente
1

Bueno, lo haría de esta manera ya que no soy bueno con Regs ..

CÓDIGO

t = '1. eat, food\n\
7am\n\
2. brush, teeth\n\
8am\n\
3. crack, eggs\n\
1pm'.splitlines()

print [i+j for i,j in zip(t[::2],t[1::2])]

salida:

['1. eat, food   7am', '2. brush, teeth   8am', '3. crack, eggs   1pm']  

Espero que esto ayude :)

Sravan K Ghantasala
fuente