2011-11-10 18 views
53

Supongamos que tengo una lista de tuplas y quiero convertirlas en varias listas.convertir la lista de tuplas en varias listas en Python

Por ejemplo, la lista de tuplas es

[(1,2),(3,4),(5,6),] 

¿Hay alguna función incorporada en Python que convertirlo a:

[1,3,5],[2,4,6] 

Esto puede ser un simple programa. Pero estoy curioso sobre la existencia de tal función incorporada en Python.

Respuesta

82

La función incorporada zip() casi hacer lo que quiera:

>>> zip(*[(1, 2), (3, 4), (5, 6)]) 
[(1, 3, 5), (2, 4, 6)] 

La única diferencia es que se obtiene tuplas en lugar de las listas. Puede convertirlos a listas usando

map(list, zip(*[(1, 2), (3, 4), (5, 6)])) 
30

Desde el python docs:

postal() en conjunto con el operador * se puede utilizar para descomprimir una lista:

Ejemplo específico:

>>> zip((1,3,5),(2,4,6)) 
[(1, 2), (3, 4), (5, 6)] 
>>> zip(*[(1, 2), (3, 4), (5, 6)]) 
[(1, 3, 5), (2, 4, 6)] 

O, si realmente quiere listas:

>>> map(list, zip(*[(1, 2), (3, 4), (5, 6)])) 
[[1, 3, 5], [2, 4, 6]] 
5

Uso:

a = [(1,2),(3,4),(5,6),]  
b = zip(*a) 
>>> [(1, 3, 5), (2, 4, 6)] 
0

Agregando a Claudiu de y de respuesta Claudiu y desde mapa tiene que ser importado de itertools en Python 3, también se utiliza una lista por comprensión como:

[[*x] for x in zip(*[(1,2),(3,4),(5,6)])] 
>>> [[1, 3, 5], [2, 4, 6]] 
0

A pesar de que *zip es más Pythonic, el siguiente código tiene un rendimiento mucho mejor:

xs, ys = [], [] 
for x, y in zs: 
    xs.append(x) 
    ys.append(y) 

Además, cuando la lista original zs está vacía, *zip aumentará, pero este código puede manejarlo correctamente.

que acaba de ejecutar un experimento rápido, y aquí está el resultado:

Using *zip:  1.54701614s 
Using append: 0.52687597s 

Correr varias veces, es append 3x - 4x más rápido que zip! La escritura de la prueba está aquí:

#!/usr/bin/env python3 
import time 

N = 2000000 
xs = list(range(1, N)) 
ys = list(range(N+1, N*2)) 
zs = list(zip(xs, ys)) 

t1 = time.time() 

xs_, ys_ = zip(*zs) 
print(len(xs_), len(ys_)) 

t2 = time.time() 

xs_, ys_ = [], [] 
for x, y in zs: 
    xs_.append(x) 
    ys_.append(y) 
print(len(xs_), len(ys_)) 

t3 = time.time() 

print('Using *zip:\t{:.8f}s'.format(t2 - t1)) 
print('Using append:\t{:.8f}s'.format(t3 - t2)) 

Mi versión de Python:

Python 3.6.3 (default, Oct 24 2017, 12:18:40) 
[GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
0

franklsf95 va para el desempeño de su respuesta y opta por list.append(), pero no son óptimas.

Adición de listas por comprensión, terminé con lo siguiente:

def t1(zs): 
    xs, ys = zip(*zs) 
    return xs, ys 

def t2(zs): 
    xs, ys = [], [] 
    for x, y in zs: 
     xs.append(x) 
     ys.append(y) 
    return xs, ys 

def t3(zs): 
    xs, ys = [x for x, y in zs], [y for x, y in zs] 
    return xs, ys 

if __name__ == '__main__': 
    from timeit import timeit 
    setup_string='''\ 
N = 2000000 
xs = list(range(1, N)) 
ys = list(range(N+1, N*2)) 
zs = list(zip(xs, ys)) 
from __main__ import t1, t2, t3 
''' 
    print(f'zip:\t\t{timeit('t1(zs)', setup=setup_string, number=1000)}') 
    print(f'append:\t\t{timeit('t2(zs)', setup=setup_string, number=1000)}') 
    print(f'list comp:\t{timeit('t3(zs)', setup=setup_string, number=1000)}') 

Esto dio el resultado:

zip:   122.11585397789766 
append:   356.44876132614047 
list comp:  144.637765085659 

Así que si usted está después de la actuación, probablemente debería utilizar zip() aunque las listas por comprensión son no muy atrás. El rendimiento de append es bastante pobre en comparación.

Cuestiones relacionadas