Wie extrahiere ich das Mitglied aus einem in Python festgelegten Einzelmitglied?

74

Ich bin kürzlich auf ein Szenario gestoßen, in dem ich etwas mit diesem Element tun wollte, wenn eine Menge nur ein einzelnes Element enthielt. Um das Element zu erhalten, habe ich mich für diesen Ansatz entschieden:

element = list(myset)[0]

Dies ist jedoch nicht sehr zufriedenstellend, da eine unnötige Liste erstellt wird. Es könnte auch mit Iteration durchgeführt werden, aber Iteration scheint auch unnatürlich, da es nur ein einziges Element gibt. Vermisse ich etwas Einfaches?

rekursiv
quelle

Antworten:

97

Das Auspacken von Tupeln funktioniert.

(element,) = myset

(Übrigens hat Python-Dev die Hinzufügung untersucht, aber abgelehnt myset.get(), ein beliebiges Element aus einer Menge zurückzugeben. Diskussion hier , Guido van Rossum antwortet 1 und 2. )

Mein persönlicher Favorit für das Erhalten eines beliebigen Elements ist (wenn Sie eine unbekannte Nummer haben, aber auch funktioniert, wenn Sie nur eine haben):

element = next(iter(myset)) ¹

1 : In Python 2.5 und früher müssen Sie verwendeniter(myset).next()

u0b34a0f6ae
quelle
9
Sehr schön! Ich mag, dass dies fehlschlägt, wenn die Anzahl der Elemente nicht 1 ist.
Laurence Gonsalves
7
Oder wenn Sie so tun möchten, als hätte Python einen geeigneten Operator für den Job (Ihre Mitarbeiter werden Sie hassen):element ,= myset
Rdb
2
Verbesserungsvorschlag: Betonen Sie, dass der erste für einen Nicht-Singleton-Satz fehlschlägt.
Ioannis Filippidis
3
Ich bin nicht so ein Fan dieses Kommas, um Python zu sagen, dass es ein Tupel ist. Wie wäre es[element] = myset
Ant6n
5
Der next(iter(myset))Ausdruck hat den Vorteil, dass er ohne spezielle Zuweisung verwendet werden kann, sodass Sie ihn beispielsweise als Argument an eine Funktion übergeben können.
LarsH
25

Zwischen dem Erstellen eines Tupels und dem Erstellen eines Iterators ist es fast eine Wäsche, aber die Iteration gewinnt durch eine Nase ...:

$ python2.6 -mtimeit -s'x=set([1])' 'a=tuple(x)[0]'
1000000 loops, best of 3: 0.465 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a=tuple(x)[0]'
1000000 loops, best of 3: 0.465 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a=next(iter(x))'
1000000 loops, best of 3: 0.456 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a=next(iter(x))'
1000000 loops, best of 3: 0.456 usec per loop

Ich bin mir nicht sicher, warum alle Antworten die ältere Syntax iter(x).next()anstelle der neuen verwenden next(iter(x)), was mir vorzuziehen scheint (und auch in Python 3.1 funktioniert).

Das Auspacken gewinnt jedoch zweifellos über beide:

$ python2.6 -mtimeit -s'x=set([1])' 'a,=x'
10000000 loops, best of 3: 0.174 usec per loop
$ python2.6 -mtimeit -s'x=set([1])' 'a,=x'
10000000 loops, best of 3: 0.174 usec per loop

Dies gilt natürlich für Sets mit einem Gegenstand (wobei die letztere Form, wie andere erwähnt haben, den Vorteil hat, schnell zu versagen, wenn der Satz, den Sie "kannten", nur einen Gegenstand hatte, tatsächlich mehrere hatte). Bei Sätzen mit beliebigen N> 1-Elementen verlangsamt sich das Tupel, der Iter nicht:

$ python2.6 -mtimeit -s'x=set(range(99))' 'a=next(iter(x))'
1000000 loops, best of 3: 0.417 usec per loop
$ python2.6 -mtimeit -s'x=set(range(99))' 'a=tuple(x)[0]'
100000 loops, best of 3: 3.12 usec per loop

Das Auspacken für den Einzelfall und next(iter(x))für den allgemeinen Fall scheint also am besten zu sein.

Alex Martelli
quelle
Warum Python2.x-Syntax? Ich programmiere dort nur wirklich und habe pythonPython 2.5 auf meinem System. Daher wird angezeigt, was passiert, wenn ich meine Tastenkombination drücke, um eine Python-Konsole zu öffnen.
u0b34a0f6ae
2.6 ist perfekt für "echte Programmierung" geeignet und umfangreicher als 2.5; Der einzige Grund, sich an 2.5 zu halten, besteht darin, dass Ihre externe Umgebung Sie einschränkt (App Engine, Civilization 4 usw.). next (x) und x.next () funktionieren beide in 2.6, aber next (x) ist besser (Sie können einen Standardwert angeben, anstatt StopIteration-Ausnahmen abzufangen, erfordert ein Zeichen weniger ;-).
Alex Martelli
@Alex: Keine Notwendigkeit mich zu überzeugen, ich würde viel lieber Python 2.6 verwenden. Ich benutze Debian, Debian hat den Übergang zu Python 2.6 noch nicht abgeschlossen! (Pyhthon 2.6 selbst ist verfügbar, aber keine der Distributionen 3. Teil Bibliotheken.)
u0b34a0f6ae
Aber da Sie erwähnen, dass dies next(..)in Python 2.6 verfügbar ist, verstehe ich Ihren Standpunkt jetzt viel besser! Das sind gute Neuigkeiten.
u0b34a0f6ae
@ kaizer.se, yep - in ähnlicher Weise ist App Engine, wie ich bereits erwähnte, nur 2.5, ebenso wie Civilization IV (andere skriptfähige Spiele und Apps können noch weiter hinten liegen), Mac OSX 10.5 (wenn Sie Apps verteilen möchten, die Verwenden Sie das System Python, anstatt es selbst zu bündeln. 10.6 verwendet schließlich Python 2.6 und so weiter. Es kann viele solcher Umgebungsbedingungen geben, die die Verwendung von 2.5 (oder sogar früheren Versionen) erzwingen. aber ja, 2.6 ist appetitlich, wenn es benutzt werden kann (die nächste eingebaute Funktion ist nur ein Leckerbissen, aber eine saftige ;-).
Alex Martelli
18

Ich denke, die Antwort von kaizer.se ist großartig. Aber wenn Ihr Satz könnte mehr als ein Element enthalten, und Sie wollen ein nicht-so-beliebiges Element, mögen Sie vielleicht verwenden minoder max. Z.B:

element = min(myset)

oder:

element = max(myset)

(Nicht verwenden sorted, da dies für diese Verwendung unnötigen Overhead bedeutet.)

Craig McQueen
quelle
Das ist der Junge. Wenn eine Menge ein Singleton ist, sollte das einzige Element darin die Min- und Max-Werte sein. Dank bro.
Samuel Nde
8

Ich schlage vor:

element = myset.pop()
Helmut
quelle
3
Dies könnte in einigen Fällen funktionieren, mutiert jedoch die Menge.
rekursiv
@recursive wie wäre eselement = myset.copy().pop()
stevepastelan
@recursive, aber spielt die Mutation eine Rolle, wenn es sich um eine Einzelelementmenge handelt?
Astrid
1
@Astrid: Für einige Anwendungsfälle ja. Für andere nein.
rekursiv
2

Sie können verwenden, element = tuple(myset)[0]was ein bisschen effizienter ist, oder Sie können so etwas tun

element = iter(myset).next()

Ich denke, das Erstellen eines Iterators ist effizienter als das Erstellen eines Tupels / einer Liste.

Oren S.
quelle
1
Warum ist das Erstellen eines Iterators Ihrer Meinung nach effizienter?
Craig McQueen
2

Es gibt auch Extended Iterable Unpacking, das für ein Singleton-Set oder ein Mulit-Element-Set geeignet ist

element, *_ = myset

Obwohl einige Borsten bei der Verwendung einer Wegwerfvariablen.

ChrisFreeman
quelle