2013-05-16 1 views
26

ich eine Liste in Python erstellt werden soll wie folgt -Python Liste Verständnis zwei Werte in einer Iteration erzeugen

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25 .....] 

Sie habe herausgefunden, ist es nichts anderes als n, n*n

Ich habe versucht, so zu schreiben eine Liste Verständnis in Python wie folgt -

Aber dies zu tun, gibt einen Syntaxfehler.

Was wäre eine gute Möglichkeit, die obige Liste über Listenverständnis zu generieren?

+1

Du wird nicht lesbar erhalten, oneliner Lösungen. Verspätete Warnung gegeben: P – ytpillai

Antwort

32

Verwendung itertools.chain.from_iterable:

>>> from itertools import chain 
>>> list(chain.from_iterable((i, i**2) for i in xrange(1, 6))) 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25] 

Oder Sie können auch eine generator Funktion:

>>> def solve(n): 
...  for i in xrange(1,n+1): 
...   yield i 
...   yield i**2 

>>> list(solve(5)) 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25] 
+1

netter als mine :) wie üblich: P –

5
lst_gen = sum([(i, i*i) for i in range(1, 10)],()) 

oh sollte ich die Summe erwähnen wahrscheinlich bricht die eine Iteration Regel :(

+3

Während dies funktioniert, gibt 'sum' auf diese Weise quadratische Leistung und so ist eine etwas gefährliche Angewohnheit zu fallen. – DSM

+0

yeert itertools wäre besser gewesen, aber ich mag den Summentrick manchmal: P –

+0

@DSM, verzeihe meine Ignoranz, warum würde die Verwendung von 'sum()' mit einem Listenverständnis (von Tupeln) quadratische Leistung ergeben? Teil meiner Frage ist, welcher Aspekt von "this way" ist das Problem? – LarsH

5

Listenkompressen erzeugen eins Element auf einmal. Ihre Optionen sind stattdessen die Schleife zu ändern, dass nur zu einem Zeitpunkt einen Wert zu generieren:

[(i//2)**2 if i % 2 else i//2 for i in range(2, 20)] 

oder Tupel zu erzeugen, dann die Liste abflachen mit itertools.chain.from_iterable():

from itertools import chain 

list(chain.from_iterable((i, i*i) for i in range(1, 10))) 

Ausgang:

>>> [(i//2)**2 if i % 2 else i//2 for i in range(2, 20)] 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81] 
>>> list(chain.from_iterable((i, i*i) for i in range(1, 10))) 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81] 
+3

Ich weiß nicht, ob ich von der ersten Lösung –

1

Eine weitere Option:

reduce(lambda x,y: x + [y, y*y], range(1,10), []) 
+0

+1 fasziniert oder angewidert sein sollte, diese ist gut – iruvar

+0

Dies erfordert den Import in Python 3. ('functools') – ytpillai

1

Eine weitere Option könnte pervers scheinen einige zu

>>> from itertools import izip, tee 
>>> g = xrange(1, 11) 
>>> x, y = tee(g) 
>>> y = (i**2 for i in y) 
>>> z = izip(x, y) 
>>> output = [] 
>>> for k in z: 
...  output.extend(k) 
... 
>>> print output 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81, 10, 100] 
3

Sie eine Liste von Listen erstellen kann dann reduzieren sie zu verbinden.

print [[n,n*n] for n in range (10)] 

[[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

print reduce(lambda x1,x2:x1+x2,[[n,n*n] for n in range (10)]) 

[0, 0, 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

print reduce(lambda x1,x2:x1+x2,[[n**e for e in range(1,4)]\ 
for n in range (1,10)]) 

[1, 1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125, 6, 36, 216, 7, 49, 343, 8, 64, 512, 9, 81, 729]

Reduzieren verwendet einen aufrufbaren Ausdruck, der zwei Argumente benötigt und eine Sequenz verarbeitet, indem er mit den ersten beiden Elementen beginnt. Das Ergebnis des letzten Ausdrucks wird dann als erstes Element in nachfolgenden Aufrufen verwendet. In diesem Fall wird jede Liste nacheinander zur ersten Liste in der Liste der Listen hinzugefügt, und dann wird diese Liste als Ergebnis zurückgegeben.

Liste Comprehensions ruft implizit Karte mit einem Lambda-Ausdruck der Variable und Sequenz durch die „für var in Sequenz“ Ausdruck definiert ist. Das Folgende ist die gleiche Art von Dingen.

map(lambda n:[n,n*n],range(1,10)) 

[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

Ich bin nicht bewusst von einem natürlichen Python-Ausdruck für reduzieren.

0
>>> lst_gen = [[i, i*i] for i in range(1, 10)] 
>>> 
>>> lst_gen 
[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]] 
>>> 
>>> [num for elem in lst_gen for num in elem] 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81] 

Hier ist meine Referenz http://docs.python.org/2/tutorial/datastructures.html

0

Versuchen Sie, diese zwei Liner

lst = [[i, i*i] for i in range(10)] 
[lst.extend(i) for i in lst] 

ändern Mathe wie nötig.

NOCH BESSER

#Change my_range to be the number you want range() function of 
start = 1 
my_range = 10 
lst = [i/2 if i % 2 == 0 else ((i-1)/2)**2 for i in range(start *2, my_range*2 - 1)] 
0

Wie bereits erwähnt, itertools ist der Weg zu gehen. Hier ist, wie ich es tun würde, finde ich es mehr klar:

[i if turn else i*i for i,turn in itertools.product(range(1,10), [True, False])] 
1

Die Frage ist alt, aber nur für den neugierigen Leser, schlage ich eine andere Möglichkeit: Wie am ersten Beitrag erwähnt, können Sie leicht ein paar machen (i, i ** 2) aus einer Liste von Zahlen. Dann willst du dieses Paar platt machen. Fügen Sie also einfach die Operation "Abflachen" in Ihr Verständnis ein.

1

Ein wenig bekannter Trick: List Comprehensions kann mehrere für Klauseln haben.

Zum Beispiel:

>>> [10*x+y for x in range(4) for y in range(3)] 
[0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32] 

In Ihrem speziellen Fall, könnten Sie tun:

>>> [x*x if y else x for x in range(5) for y in range(2)] 
[0, 0, 1, 1, 2, 4, 3, 9, 4, 16]