2009-12-10 11 views
5

Ho una lista di liste (generato con un semplice elenco di comprensione):Conversione di un elenco di liste ad una tupla in Python

>>> base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 
>>> base_lists 

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

voglio trasformare questa intera lista in una tupla contenente tutti i valori negli elenchi, ovvero:

resulting_tuple = (1,1,1,2,1,3,1,4,1,5,2,1,2,2,2,3,2,4,2,5) 

Quale sarebbe il modo più efficace per farlo? (Un modo per generare questa stessa tupla con la comprensione delle liste sarebbe anche una risposta accettabile.) Ho esaminato le risposte qui e nella documentazione di Python, tuttavia non sono riuscito a trovarne una adatta.

EDIT:

Molte grazie a tutti coloro che hanno risposto!

risposta

11
tuple(x for sublist in base_lists for x in sublist) 

Edit: notare che, con base_lists così breve, il genexp (con memoria illimitata disponibili) è lento. Si consideri il seguente file tu.py:

base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 

def genexp(): 
    return tuple(x for sublist in base_lists for x in sublist) 

def listcomp(): 
    return tuple([x for sublist in base_lists for x in sublist]) 

def withsum(): 
    return tuple(sum(base_lists,[])) 

import itertools as it 

def withit(): 
    return tuple(it.chain(*base_lists)) 

Ora:

$ python -mtimeit -s'import tu' 'tu.genexp()' 
100000 loops, best of 3: 7.86 usec per loop 
$ python -mtimeit -s'import tu' 'tu.withsum()' 
100000 loops, best of 3: 5.79 usec per loop 
$ python -mtimeit -s'import tu' 'tu.withit()' 
100000 loops, best of 3: 5.17 usec per loop 
$ python -mtimeit -s'import tu' 'tu.listcomp()' 
100000 loops, best of 3: 5.33 usec per loop 

Quando le liste sono più (cioè, quando le prestazioni che conta davvero) le cose sono un po 'diverso. Ad esempio, mettendo un 100 * sul RHS definendo base_lists:

$ python -mtimeit -s'import tu' 'tu.genexp()' 
1000 loops, best of 3: 408 usec per loop 
$ python -mtimeit -s'import tu' 'tu.withsum()' 
100 loops, best of 3: 5.07 msec per loop 
$ python -mtimeit -s'import tu' 'tu.withit()' 
10000 loops, best of 3: 148 usec per loop 
$ python -mtimeit -s'import tu' 'tu.listcomp()' 
1000 loops, best of 3: 278 usec per loop 

così per lunghe liste solo withsum è un disastro prestazioni - gli altri sono nella stessa ballpark, anche se chiaramente itertools ha il bordo, e la list comprehension (quando è disponibile una memoria abbondante, come sempre nei microbenchmarks ;-) sono più veloci dei genexps.

Utilizzando 1000 *, genexp rallenta di circa 10 volte (rispetto alla 100 *), withit e listcomp di circa 12 volte, e withsum di circa 180 volte (withsum è O(N squared), più si comincia a soffrire di grave frammentazione mucchio in quel dimensione).

+0

fa esattamente quello che mi serve. Grazie Alex! –

3
>>> sum(base_lists,[]) 
[1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5] 
>>> tuple(sum(base_lists,[])) 
(1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5) 
+2

Usare 'sum' per qualsiasi cosa, ma i numeri sono una cattiva idea (come ho spesso cercato di spiegare in SO - Sono stato il creatore del' sum' di Python, quindi provo un senso di colpa ogni volta che lo vedo male ;-) . Suggerimento: O (N al quadrato). –

+0

Ouch, buono a sapersi, grazie Alex. Suppongo che ci sia una buona ragione per cui non può essere O (N):/ –

2

resulting_tuple = tuple(item for l in base_lists for item in l)

5
from itertools import chain 
base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 

print tuple(chain(*base_lists)) 
+0

Votato per l'uso di itertools, che è un modulo sottostimato –

0
>>> arr=[] 
>>> base_lists = [[a, b] for a in range(1, 3) for b in range(1, 6)] 
>>> [ arr.extend(i) for i in base_lists ] 
[None, None, None, None, None, None, None, None, None, None] 
>>> arr 
[1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5] 
>>> tuple(arr) 
(1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 2, 1, 2, 2, 2, 3, 2, 4, 2, 5) 
Problemi correlati