webentwicklung-frage-antwort-db.com.de

Wie erhalte ich den Index einer Ganzzahl aus einer Liste, wenn die Liste einen Booleschen Wert enthält?

Ich fange gerade mit Python an.

Wie erhalte ich den Index der Ganzzahl 1 aus einer Liste, wenn die Liste ein boolesches Objekt True vor dem 1 enthält?

>>> lst = [True, False, 1, 3]
>>> lst.index(1)
0
>>> lst.index(True)
0
>>> lst.index(0)
1

Ich denke, Python betrachtet 0 als False und 1 als True im Argument der index-Methode. Wie kann ich den Index der Ganzzahl 1 (d. H. 2) abrufen?

Welche Argumentation oder Logik steckt dahinter, boolesche Objekte in der Liste so zu behandeln? Wie aus den Lösungen hervorgeht, ist es nicht so einfach.

14

Die Dokumentation sagt das

Listen sind veränderbare Sequenzen, die normalerweise zum Speichern von Sammlungen homogener Elemente verwendet werden (wobei der genaue Ähnlichkeitsgrad je nach Anwendung variiert).

Sie sollten keine heterogenen Daten in Listen speichern. Die Implementierung von list.index führt den Vergleich nur mit Py_EQ (Operator ==) durch. In Ihrem Fall gibt dieser Vergleich einen Wahrheitswert zurück, da True und False Werte der ganzen Zahlen 1 bzw. 0 haben ( die Bool-Klasse ist schließlich eine Unterklasse von int ).

Sie können jedoch den Generatorausdruck und die integrierte Funktion next (um den ersten Wert vom Generator zu erhalten) wie folgt verwenden:

In [4]: next(i for i, x in enumerate(lst) if not isinstance(x, bool) and x == 1)
Out[4]: 2

Hier prüfen wir, ob x eine Instanz von bool ist vor und vergleichen x mit 1.

Denken Sie daran, dass nextStopIteration auslösen kann. In diesem Fall kann es erwünscht sein, ValueError (um das Verhalten von list.index nachzuahmen) (erneut) auszulösen.

Dies alles in eine Funktion packen:

def index_same_type(it, val):
    gen = (i for i, x in enumerate(it) if type(x) is type(val) and x == val)
    try:
        return next(gen)
    except StopIteration:
        raise ValueError('{!r} is not in iterable'.format(val)) from None

Einige Beispiele:

In [34]: index_same_type(lst, 1)
Out[34]: 2

In [35]: index_same_type(lst, True)
Out[35]: 0

In [37]: index_same_type(lst, 42)
ValueError: 42 is not in iterable
13
vaultah

Boolesche sind Ganzzahlen in Python, und aus diesem Grund können Sie sie wie jede andere Ganzzahl verwenden:

>>> 1 + True
2
>>> [1][False]
1

[das heißt nicht, dass du es solltest :)]

Dies liegt an der Tatsache, dass bool eine Unterklasse von int ist und sich fast immer wie 0 oder 1 verhält (außer wenn es in einen String umgewandelt wird - Sie erhalten stattdessen "False" und "True").

Hier ist noch eine Idee, wie Sie erreichen können, was Sie wollen (versuchen Sie jedoch, Ihre Logik unter Berücksichtigung der obigen Informationen zu überdenken):

>>> class force_int(int):
...     def __eq__(self, other):
...         return int(self) == other and not isinstance(other, bool)
... 
>>> force_int(1) == True
False
>>> lst.index(force_int(1))
2

Dieser Code definiert die Methode von int neu, die zum Vergleichen von Elementen in der Methode index verwendet wird, um boolesche Werte zu ignorieren.

8

Hier ist eine sehr einfache naive einzeilige Lösung mit map und Zip :

>>> Zip(map(type, lst), lst).index((int, 1))
2

Hier ordnen wir den Typ jedes Elements zu und erstellen eine neue Liste, indem wir die Typen mit den Elementen zippen und nach dem Index von (type, value) fragen.

Und hier ist eine allgemeine iterative Lösung, die dieselbe Technik verwendet:

>>> from itertools import imap, izip
>>> def index(xs, x):
...     it = (i for i, (t, e) in enumerate(izip(imap(type, xs), xs)) if (t, e) == x)
...     try:
...             return next(it)
...     except StopIteration:
...             raise ValueError(x)
... 
>>> index(lst, (int, 1))
2

Hier machen wir im Grunde das Gleiche , aber iterativ, um uns nicht viel Speicherplatz zu kosten. Wir sind ein Iterator desselben Ausdrucks von oben, verwenden jedoch stattdessen imap und izip und erstellen eine benutzerdefinierte Indexfunktion, die den nächsten Wert aus dem Iterator zurückgibt, oder erhöhen eine ValueError, wenn keine Übereinstimmung vorliegt.

5
James Mills

Versuchen Sie dies.

for i, j in enumerate([True, False, 1, 3]):
    if not isinstance(j, bool) and j == 1:
        print i

Ausgabe:

2
0
Haresh Shyara