Python List Comprehensions: Ist es möglich, die Aufnahme von zwei Elementen gleichzeitig zu spezifizieren? - Python, Listenverständnis

Bis zu diesem Zeitpunkt habe ich in Python nur Listen-Comprehensions gesehen, die die Aufnahme eines Elements zur Zeit angeben. Zum Beispiel sind sie alle in der folgenden Form

[f(x) for x in <iterable>]

Gibt es eine Möglichkeit, mehr als ein Element gleichzeitig anzugeben? Beispielsweise,

[f(x), g(x) for x in <iterable>]

Ich frage, weil ich ein Listenverständnis erstellen möchte, das alle Teiler einer Zahl x berechnet, aber ich möchte das so effizient wie möglich machen. Im Moment benutze ich folgendes,

[y for y in range(1,x+1) if x%y == 0]

aber ich würde gerne so etwas machen,

[y, x/y for y in range(1, sqrt(x)+1) if x%y == 0]

wie dies effizienter wäre.Übrigens, ich habe keinen praktischen Grund dafür. Es ist einfach ein Herausforderungsproblem, das mir jemand gesagt hat, und das Ziel ist, es mit dem kleinsten, effizientesten Listenverständnis zu tun.

Danke im Voraus.

Bearbeiten: Ok, es sieht so aus als müsste ich Tupel benutzen. Ich habe versucht, das zu vermeiden, obwohl ich dann eine andere Funktion machen müsste, um die Liste zu verflachen, was meine Lösung länger machen würde.

Bearbeiten 2: Für den Fall, dass jemand auf diese Frage stößt, lautet die Antwort auf das, was ich in meiner ursprünglichen Frage machen wollte:

[y for x in <iterable> for y in f(x), g(x)]

Es verwendet verschachtelte for-Schleifen im Listenverständnis, um die Aufgabe zu erledigen.

Antworten:

3 für die Antwort № 1

Sie können Tupeln zuweisen

[(y, x/y) for y in range(1, int(sqrt(x))+1) if x%y == 0]

Nicht wirklich verwandt mit deiner Grundfrage, aber dein Beispiel: Ich musste den 2. Parameter von konvertieren range() zu einem int schon seit sqrt() führte zu einem float in meinem Testcode.

Aktualisieren Re Bearbeiten in der Post:

Um diese Liste von Tupeln zu reduzieren:

In [24]: s
Out[24]: [(1, 20), (2, 10), (4, 5)]

benutze das:

In [25]: import operator

Erzeuge ein Tupel:

In [26]: reduce(operator.add, s, ())
Out[26]: (1, 20, 2, 10, 4, 5)

Erstelle eine Liste:

In [27]: list(reduce(operator.add, s, ()))
Out[27]: [1, 20, 2, 10, 4, 5]

Hinweis: In einem hilfreichen Kommentar weist @jamylak darauf hin reduce und operator.add rufe die Reihenfolge O (N ^ 2) und die Verwendung von itertools.chain wäre viel effizienter. Dies wird mit zunehmender Größe der Liste wichtiger und sollte in diesem Fall berücksichtigt werden.


4 für die Antwort № 2

Sie können es an Ort und Stelle glätten

[y if i else x/y for y in range(1, sqrt(x)+1) for i in 0,1 if x%y == 0]

3 für die Antwort № 3

Ja, du kannst es tun. Sie müssen nur Klammern um das Element setzen. Was Sie bekommen, ist eine Liste von Tupeln.

>>> [(x, x+1) for x in range(5)]
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]

2 für die Antwort № 4

Oh, so nah:

[(y, x/y) for y in range(1, sqrt(x)+1) if x%y == 0]

Es ist möglich, eine Liste von Tupeln zu erzeugen, und diese können natürlich mehrere Werte enthalten.


1 für die Antwort № 5

Ja, verwenden Sie einfach Klammern um den Wert:

[(y, x/y) for y in range(1, sqrt(x)+1) if x%y == 0]