2009-12-10 13 views
5

Mam listę list (wygenerowany z prostym listowego):Konwersja listę list do krotki w Pythonie

>>> 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]] 

chcę obrócić całą tę listę na krotki zawierającej wszystkie wartości na listach, tj .:

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

Jaki byłby najskuteczniejszy sposób, aby to zrobić? (Sposób na wygenerowanie tej samej krotki ze zrozumieniem listy byłby również akceptowalną odpowiedzią). Przyjrzałem się odpowiedziom tutaj i w dokumentacji Pythona, jednak nie byłem w stanie znaleźć odpowiedniego.

EDIT:

Wielkie dzięki dla wszystkich, którzy odpowiedzieli!

Odpowiedz

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

Edit: zauważ, że z base_lists tak krótki, genexp (z nieograniczoną dostępnej pamięci) jest powolny. Rozważmy następujący plik 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)) 

Teraz:

$ 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 

Gdy wykazy są dłuższe (tj gdy wydajność jest naprawdę ważne) rzeczy są nieco odmienne. Na przykład umieszczenie 100 * na RHS definiowania 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 

więc na długich listach tylko withsum jest katastrofa wydajność - inni są w tym samym pole do gry, choć wyraźnie itertools ma przewagę i listowych (gdy obfitość pamięci jest dostępna, ponieważ zawsze będzie w mikrobenkach ;-) są szybsze niż genexp.

Stosując 1000 *, genexp spowalnia około 10 razy (wrt 100 *) withit i listcomp przez około 12 godziny i withsum około 180 razy (withsum jest O(N squared), plus zaczyna cierpią na poważny fragmentacji sterty w tamtym rozmiar).

+0

Czy właśnie to, czego potrzebuję. Dziękuję 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

Używanie 'sum' dla czegokolwiek oprócz liczb jest złym pomysłem (jak to często próbowałem wytłumaczyć w SO - byłem twórcą' sumy 'Pythona, więc odczuwam ukłucie winy za każdym razem, gdy widzę, że jest źle używane ;-) . Wskazówka: O (N do kwadratu). –

+0

Dobra, dobrze wiedzieć dzięki Alex. Sądzę, że będzie dobry powód, dla którego nie może to być 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

Zagłosowano za używanie itertools, który jest niedocenianym modułem –

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) 
Powiązane problemy