Frage Wählen Sie explizit Elemente aus einer Python-Liste oder einem Tupel aus


Ich habe die folgende Python-Liste (kann auch ein Tupel sein):

myList = ['foo', 'bar', 'baz', 'quux']

ich kann sagen

>>> myList[0:3]
['foo', 'bar', 'baz']
>>> myList[::2]
['foo', 'baz']
>>> myList[1::2]
['bar', 'quux']

Wie wähle ich explizit Elemente aus, deren Indizes keine spezifischen Muster haben? Zum Beispiel möchte ich auswählen [0,2,3]. Oder aus einer sehr großen Liste von 1000 Artikeln, die ich auswählen möchte [87, 342, 217, 998, 500]. Gibt es eine Python-Syntax, die das tut? Etwas, das wie folgt aussieht:

>>> myBigList[87, 342, 217, 998, 500]

76
2017-07-09 01:49


Ursprung


Antworten:


list( myBigList[i] for i in [87, 342, 217, 998, 500] )

Ich habe die Antworten mit Python 2.5.2 verglichen:

  • 19.7 Usec: [ myBigList[i] for i in [87, 342, 217, 998, 500] ]

  • 20.6 Usec: map(myBigList.__getitem__, (87, 342, 217, 998, 500))

  • 22.7 Usec: itemgetter(87, 342, 217, 998, 500)(myBigList)

  • 24.6 Usec: list( myBigList[i] for i in [87, 342, 217, 998, 500] )

Beachten Sie, dass in Python 3 der 1. geändert wurde, um derselbe wie der 4. zu sein.


Eine andere Möglichkeit wäre, mit einem zu beginnen numpy.array welches die Indexierung über eine Liste oder ein numpy.array:

>>> import numpy
>>> myBigList = numpy.array(range(1000))
>>> myBigList[(87, 342, 217, 998, 500)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: invalid index
>>> myBigList[[87, 342, 217, 998, 500]]
array([ 87, 342, 217, 998, 500])
>>> myBigList[numpy.array([87, 342, 217, 998, 500])]
array([ 87, 342, 217, 998, 500])

Das tuple funktioniert nicht genauso wie diese Slices.


97
2017-07-09 01:53



Was ist damit?

from operator import itemgetter
itemgetter(0,2,3)(myList)
('foo', 'baz', 'quux')

31
2017-07-09 01:52



Es ist nicht integriert, aber Sie können eine Unterklasse der Liste erstellen, die Tupel als "Indizes" verwendet, wenn Sie möchten:

class MyList(list):

    def __getitem__(self, index):
        if isinstance(index, tuple):
            return [self[i] for i in index]
        return super(MyList, self).__getitem__(index)


seq = MyList("foo bar baaz quux mumble".split())
print seq[0]
print seq[2,4]
print seq[1::2]

Drucken

foo
['baaz', 'mumble']
['bar', 'quux']

9
2017-07-09 01:57



>>> map(myList.__getitem__, (2,2,1,3))
('baz', 'baz', 'bar', 'quux')

Sie können auch Ihre eigenen erstellen List Klasse, die Tupel als Argumente unterstützt __getitem__ wenn du es können willst myList[(2,2,1,3)].


5
2017-07-09 02:02



Vielleicht ist ein Listenverständnis in Ordnung:

L = ['a', 'b', 'c', 'd', 'e', 'f']
print [ L[index] for index in [1,3,5] ]

Produziert:

['b', 'd', 'f']

Ist das wonach Sie suchen?


3
2017-07-09 02:00



Ich möchte nur darauf hinweisen, dass die Syntax von itemgetter wirklich gut aussieht, aber es ist ziemlich langsam, wenn man sie auf einer großen Liste ausführt.

import timeit
from operator import itemgetter
start=timeit.default_timer()
for i in range(1000000):
    itemgetter(0,2,3)(myList)
print ("Itemgetter took ", (timeit.default_timer()-start))

Itemgetter hat 1.065209062149279 genommen

start=timeit.default_timer()
for i in range(1000000):
    myList[0],myList[2],myList[3]
print ("Multiple slice took ", (timeit.default_timer()-start))

Mehrere Schnitte nahmen 0,6225321444745759


0
2017-11-01 14:50



Eine andere mögliche Lösung:

sek=[]
L=[1,2,3,4,5,6,7,8,9,0]
for i in [2, 4, 7, 0, 3]:
   a=[L[i]]
   sek=sek+a
print (sek)

0
2017-11-18 20:32



wie oft, wenn Sie ein boolesches numpy array mögen mask

[mylist[i] for i in np.arange(len(mask), dtype=int)[mask]]

Ein Lambda, das für jede Sequenz oder jedes np.array funktioniert:

subseq = lambda myseq, mask : [myseq[i] for i in np.arange(len(mask), dtype=int)[mask]]

newseq = subseq(myseq, mask)


0
2017-07-16 15:26