72 Stimmen

Pythons Methode list index() auf eine Liste von Tupeln oder Objekten anwenden?

Pythons Listentyp hat eine index()-Methode, die einen Parameter annimmt und den Index des ersten Elements in der Liste zurückgibt, das dem Parameter entspricht. Zum Beispiel:

>>> some_list = ["apple", "pear", "banana", "grape"]
>>> some_list.index("pear")
1
>>> some_list.index("grape")
3

Gibt es eine elegante (idiomatische) Möglichkeit, dies auf Listen komplexer Objekte, wie Tupel, auszuweiten? Im Idealfall möchte ich in der Lage sein, so etwas wie dieses zu tun:

>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
>>> some_list.getIndexOfTuple(1, 7)
1
>>> some_list.getIndexOfTuple(0, "kumquat")
2

getIndexOfTuple() ist nur eine hypothetische Methode, die einen Subindex und einen Wert akzeptiert und dann den Index des Listenelements mit dem angegebenen Wert an diesem Subindex zurückgibt. Ich hoffe

Gibt es eine Möglichkeit, dieses allgemeine Ergebnis zu erreichen, indem man Listenauflösungen oder Lambas oder etwas ähnliches "in-line" verwendet? Ich denke, ich könnte meine eigene Klasse und Methode schreiben, aber ich möchte nicht das Rad neu erfinden, wenn Python bereits eine Möglichkeit, es zu tun hat.

83voto

Paolo Bergantino Punkte 465120

Wie wäre es damit?

>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
>>> [x for x, y in enumerate(tuple_list) if y[1] == 7]
[1]
>>> [x for x, y in enumerate(tuple_list) if y[0] == 'kumquat']
[2]

Wie in den Kommentaren erwähnt, würde dies alle Spiele erhalten. Um nur den ersten zu erhalten, können Sie tun:

>>> [y[0] for y in tuple_list].index('kumquat')
2

In den Kommentaren gibt es eine gute Diskussion über den Geschwindigkeitsunterschied zwischen den verschiedenen Lösungen. Ich bin vielleicht etwas voreingenommen, aber ich persönlich würde mich an einen Einzeiler halten, da die Geschwindigkeit, über die wir hier sprechen, im Vergleich zum Erstellen von Funktionen und Importieren von Modulen für dieses Problem ziemlich unbedeutend ist, aber wenn Sie planen, dies mit einer sehr großen Anzahl von Elementen zu tun, sollten Sie sich vielleicht die anderen Antworten ansehen, da sie schneller sind als die von mir bereitgestellten.

30voto

Kenan Banks Punkte 196831

Diese Listen sind nach einer Weile unübersichtlich.

Ich mag diesen pythonischen Ansatz:

from operator import itemgetter

def collect(l, index):
   return map(itemgetter(index), l)

# And now you can write this:
collect(tuple_list,0).index("cherry")   # = 1
collect(tuple_list,1).index("3")        # = 2

Wenn Ihr Code besonders leistungsfähig sein soll:

# Stops iterating through the list as soon as it finds the value
def getIndexOfTuple(l, index, value):
    for pos,t in enumerate(l):
        if t[index] == value:
            return pos

    # Matches behavior of list.index
    raise ValueError("list.index(x): x not in list")

getIndexOfTuple(tuple_list, 0, "cherry")   # = 1

11voto

Jarret Hardie Punkte 89900

Eine Möglichkeit ist die Verwendung der itemgetter Funktion aus der operator Modul:

import operator

f = operator.itemgetter(0)
print map(f, tuple_list).index("cherry") # yields 1

Die Aufforderung an itemgetter gibt eine Funktion zurück, die das Äquivalent zu foo[0] für alles, was an sie weitergegeben wird. Verwendung von map wenden Sie diese Funktion dann auf jedes Tupel an und extrahieren die Informationen in eine neue Liste, die Sie dann aufrufen index wie gewohnt.

map(f, tuple_list)

ist gleichbedeutend mit:

[f(tuple_list[0]), f(tuple_list[1]), ...etc]

was wiederum gleichbedeutend ist mit:

[tuple_list[0][0], tuple_list[1][0], tuple_list[2][0]]

das ergibt:

["pineapple", "cherry", ...etc]

9voto

Alasdair Punkte 275312

Sie können dies mit einem Listenverständnis und index() tun

tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
[x[0] for x in tuple_list].index("kumquat")
2
[x[1] for x in tuple_list].index(7)
1

7voto

Claudiu Punkte 215027

Inspiriert durch diese Frage Ich fand das sehr elegant:

>>> tuple_list = [("pineapple", 5), ("cherry", 7), ("kumquat", 3), ("plum", 11)]
>>> next(i for i, t in enumerate(tuple_list) if t[1] == 7)
1
>>> next(i for i, t in enumerate(tuple_list) if t[0] == "kumquat")
2

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X