2009-12-10 6 views
5

Konvertieren habe ich eine Liste von Listen (mit einem einfachen Liste Verständnis generierte):eine Liste von Listen zu einem Tupel 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]] 

Ich mag diese ganze Liste in ein Tupel drehen alle Werte enthält, in den Listen, dh:

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

Was wäre der effektivste Weg, dies zu tun? (Eine Möglichkeit, dasselbe Tupel mit Listenverständnis zu erzeugen, wäre auch eine akzeptable Antwort.) Ich habe die Antworten hier und in der Python-Dokumentation angeschaut, aber ich konnte keine passende finden.

EDIT:

Vielen Dank an alle, die beantwortet!

Antwort

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

bearbeitet: zur Kenntnis, dass mit base_lists so kurz, die genexp (mit unbegrenztem Speicher verfügbar) ist langsam. Betrachten Sie die folgende Datei 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)) 

Jetzt:

$ 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 

Wenn Listen sind länger (das heißt, wenn die Leistung wirklich zählt) die Dinge ein wenig anders sind. ZB ein 100 * auf der RHS setzen definieren 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 

so für withsum lange Listen nur eine Leistung Katastrophe ist - die andere in derselben Liga, obwohl klar itertools den Rand, und Listenkomprehensionen (wenn reichlich Speicher ist verfügbar, wie es immer in microbenchmarks sein wird ;-) sind schneller als genexps.

Mit 1000 *, genexp verlangsamt um etwa das 10-fache (WRT die 100 *), withit und listcomp von etwa 12 mal, und withsum um etwa 180-mal nach unten (withsum ist O(N squared), plus es fängt an schweren Heapfragmentierung an, dass zu leiden Größe).

+0

tut genau das, was ich brauche. Danke 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

Die Verwendung von 'sum' für alles außer Zahlen ist eine schlechte Idee (wie ich oft versucht habe, in SO zu erklären - ich war der Urheber von Pythons" Summe ", also fühle ich einen Schuldgefühle, wenn ich es missbraucht sehe ;-) . Hinweis: O (N-Quadrat). –

+0

Autsch, gut zu wissen danke Alex. Ich denke, es wird einen guten Grund geben, warum es nicht O (N) sein kann:/ –

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

Für die Verwendung von itertools, die ein unterschätztes Modul ist, abgestimmt –

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) 
Verwandte Themen