2013-08-16 8 views
112

Potrzebuję wybrać niektóre elementy z podanej listy, znając ich indeks. Powiedzmy, że chciałbym utworzyć nową listę, która zawiera element o indeksie 1, 2, 5 z podanej listy [-2, 1, 5, 3, 8, 5, 6]. Co zrobiłem:Dostęp do wielu elementów listy znających ich indeks

a = [-2,1,5,3,8,5,6] 
b = [1,2,5] 
c = [ a[i] for i in b] 

Czy istnieje lepszy sposób to zrobić? coś w stylu c = a [b]?

+0

przy okazji, znalazłem inne rozwiązanie tutaj . Nie testowałem jeszcze tego, ale myślę, że mogę opublikować go tutaj, gdy jesteś zainteresowany http://code.activestate.com/recipes/577953-get-multiple-elements-from-a-list/ –

+0

To jest takie samo rozwiązanie, jak wspomniane w pytaniu, ale owinięte w funkcję 'lambda'. –

+0

Możliwy duplikat [jak wyodrębnić elementy z listy w pythonie?] (Https://stackoverflow.com/questions/2621674/how-to-extract-elements-from-a-list-in-python) – jdhao

Odpowiedz

113

Można użyć operator.itemgetter:

from operator import itemgetter 
a = [-2, 1, 5, 3, 8, 5, 6] 
b = [1, 2, 5] 
print itemgetter(*b)(a) 
# Result: 
(1, 5, 5) 

Albo można użyć numpy:

import numpy as np 
a = np.array([-2, 1, 5, 3, 8, 5, 6]) 
b = [1, 2, 5] 
print list(a[b]) 
# Result: 
[1, 5, 5] 

Ale tak naprawdę, twoje obecne rozwiązanie jest w porządku. To chyba najmodniejszy z nich wszystkich.

+14

+1 dla wspomnienia, że ​​'c = [a [i] dla i in b]' jest całkowicie w porządku. Zauważ, że rozwiązanie 'itemgetter' nie zrobi tego samego, jeśli b ma mniej niż 2 elementy. – flornquake

+0

** Strona ** ** Uwaga **: Używanie _itemgetter_ podczas pracy w trybie wieloetapowym nie działa. Numpy działa świetnie w wielu procesach. –

+0

Dodatkowy komentarz, 'a [b]' działa ** tylko ** gdy 'a' jest tablicą ** numpy **, tzn. Tworzysz ją za pomocą funkcji numpy. –

22

Alternatywy:

>>> map(a.__getitem__, b) 
[1, 5, 5] 

>>> import operator 
>>> operator.itemgetter(*b)(a) 
(1, 5, 5) 
0

Moja odpowiedź nie używa kolekcji numpy lub python.

jeden trywialny sposób na znalezienie elementów będzie w następujący sposób:

a = [-2, 1, 5, 3, 8, 5, 6] 
b = [1, 2, 5] 
c = [i for i in a if i in b] 

wadę: Metoda ta może nie działać w przypadku większych list. Używanie numpy jest zalecane dla większych list.

+3

Nie ma potrzeby powtarzania "a". '[a [i] for i in b]' – falsetru

+0

Ta metoda nie działa nawet w żadnym innym przypadku. Co jeśli 'a' ma w sobie kolejne 5? – TerryA

+0

IMO, szybciej zrobić tego rodzaju skrzyżowanie za pomocą [sets] (https://docs.python.org/3/tutorial/datastructures.html#sets) – sirgogo

3

podstawowe i nie bardzo rozległe badania porównując czas realizacji pięciu dostarczonych odpowiedzi na:

def numpyIndexValues(a, b): 
    na = np.array(a) 
    nb = np.array(b) 
    out = list(na[nb]) 
    return out 

def mapIndexValues(a, b): 
    out = map(a.__getitem__, b) 
    return list(out) 

def getIndexValues(a, b): 
    out = operator.itemgetter(*b)(a) 
    return out 

def pythonLoopOverlap(a, b): 
    c = [ a[i] for i in b] 
    return c 

multipleListItemValues = lambda searchList, ind: [searchList[i] for i in ind] 

stosując następujące dane wejściowe:

a = range(0, 10000000) 
b = range(500, 500000) 

prosta pętla pyton był najszybszym z pracy lambda A close second, mapIndexValues ​​i getIndexValues ​​były dość podobne, a metoda numpy znacznie wolniej po konwersji list na numpy. Jeśli dane są już w numpy tablice, metoda numpyIndexValues ​​z numpy Konwersja .array została usunięta najszybciej.

numpyIndexValues -> time:1.38940598 (when converted the lists to numpy arrays) 
numpyIndexValues -> time:0.0193445 (using numpy array instead of python list as input, and conversion code removed) 
mapIndexValues -> time:0.06477512099999999 
getIndexValues -> time:0.06391049500000001 
multipleListItemValues -> time:0.043773591 
pythonLoopOverlap -> time:0.043021754999999995 
+0

Nie wiem, jakiego interpretera Python używasz, ale pierwszą metodę. numpyIndexValues' nie działa, ponieważ 'a',' b' są typu 'range'. Zgaduję, że chcesz najpierw przekonwertować 'a',' b' na 'numpy.ndarrays'? – strpeter

+0

@strpeter Tak, ja nie porównywałem jabłek z jabłkami, stworzyłem numpy tablice jako dane wejściowe w przypadku testowym dla numpyIndexValues. Naprawiłem to teraz i wszystkie używają tych samych list jako danych wejściowych. –

2

Jestem pewien, że to już zostało uznane: Jeśli ilość wskaźników w B jest mały i stały, można po prostu napisać wynik takiego:

c = [a[b[0]]] + [a[b[1]]] + [a[b[2]]] 

lub nawet prostsze, jeśli indeksów same są stałe ...

c = [a[1]] + [a[2]] + [a[5]] 

Lub jeśli istnieje kolejny zakres wskaźników ...

c = a[1:3] + [a[5]] 
+0

Dziękuję za przypomnienie, że '[a] + [b] = [a, b]' – onewhaleid

1

Innym rozwiązaniem mogłoby być poprzez Series pandy:

import pandas as pd 

a = pd.Series([-2, 1, 5, 3, 8, 5, 6]) 
b = [1, 2, 5] 
c = a[b] 

można następnie przekształcić c powrót do listy, jeśli chcesz:

c = list(c) 
Powiązane problemy