Wie indiziere ich in Python eine Liste mit einer anderen Liste?


130

Ich möchte eine Liste mit einer anderen Liste wie dieser indizieren

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
T = L[ Idx ]

und T sollte eine Liste sein, die ['a', 'd', 'h'] enthält.

Gibt es einen besseren Weg als

T = []
for i in Idx:
    T.append(L[i])

print T
# Gives result ['a', 'd', 'h']

Antworten:


241
T = [L[i] for i in Idx]

6
Ist das schneller als eine for-Schleife oder nur kürzer?
Daniel Andrén

9
@ Daniel: beide + empfohlen
SilentGhost

13
Ein schneller Timing-Test (kein Pysco oder so, machen Sie es so, wie Sie wollen) zeigte, dass das Listenverständnis 2,5-mal schneller ist als die Schleife (1000 Elemente, 10000-mal wiederholt).
James Hopkin

2
(Die Verwendung von Karte und Lambda ist noch langsamer - zu erwarten, da für jede Iteration eine Funktion aufgerufen wird)
James Hopkin

+1 Wenn die Indizierungsliste willkürlich ist, ist eine Listenkomprimierung der Weg. Ich denke jedoch, dass Scheiben, wenn möglich, was hier nicht der Fall zu sein scheint, noch schneller sind.
Jaime

40

Wenn Sie Numpy verwenden, können Sie das erweiterte Schneiden folgendermaßen durchführen:

>>> import numpy
>>> a=numpy.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
>>> Idx = [0, 3, 7]
>>> a[Idx]
array(['a', 'd', 'h'], 
      dtype='|S1')

... und ist wahrscheinlich viel schneller (wenn die Leistung ausreicht, um sich um den Numpy-Import zu kümmern)


5
Mein schneller Timeit-Test hat gezeigt, dass die Verwendung von np.array tatsächlich fast dreimal langsamer ist (einschließlich der Konvertierung in ein Array).
Andrzej Pronobis

Es funktioniert besser, wenn Sie es sowieso für Array-Operationen konvertieren müssen. Zu zeitaufwändig für regelmäßige Listenoperationen.
Frankliuao

9

Ein funktionaler Ansatz:

a = [1,"A", 34, -123, "Hello", 12]
b = [0, 2, 5]

from operator import itemgetter

print(list(itemgetter(*b)(a)))
[1, 34, 12]

Dies funktioniert nicht, wenn bnur ein Element enthalten ist.
Blhsing


5

Ich war mit keinem dieser Ansätze zufrieden und habe eine FlexlistKlasse entwickelt, die eine flexible Indizierung ermöglicht, entweder nach Ganzzahl, Slice oder Indexliste:

class Flexlist(list):
    def __getitem__(self, keys):
        if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
        return [self[k] for k in keys]

Was Sie für Ihr Beispiel verwenden würden als:

L = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Idx = [0, 3, 7]
T = L[ Idx ]

print(T)  # ['a', 'd', 'h']

Dies zeigt auch die Leistungsfähigkeit und Flexibilität von Python!
Crowie

Es ist so einfach, dies auch für vorhandenen Code zu erweitern. Rufen Sie einfach an existing_list = Flexlist(existing_list)und wir haben die erforderliche Funktionalität, ohne Code zu
beschädigen

1
L= {'a':'a','d':'d', 'h':'h'}
index= ['a','d','h'] 
for keys in index:
    print(L[keys])

Ich würde eine Verwendung Dict addgewünscht keyszuindex


0

Sie können die __getitem__Methode auch mapwie folgt kombinieren :

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
res = list(map(L.__getitem__, Idx))
print(res)
# ['a', 'd', 'h']
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.