index()poda tylko pierwsze wystąpienie elementu na liście. Czy istnieje fajna sztuczka, która zwraca wszystkie indeksy na liście?
index()poda tylko pierwsze wystąpienie elementu na liście. Czy istnieje fajna sztuczka, która zwraca wszystkie indeksy na liście?
Odpowiedzi:
Możesz użyć rozumienia listy:
indices = [i for i, x in enumerate(my_list) if x == "whatever"]
enumeratew wersji 2.3. Więc tak, jeśli twój Python jest starożytny, użyj filter().
print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])zwraca []zamiast [[0, 1], [0, 0], [1, 1]].
(a == 1).nonzero()dla tablicy NumPy a.
Chociaż nie jest to rozwiązanie dla list bezpośrednio, numpynaprawdę błyszczy dla tego rodzaju rzeczy:
import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval = 3
ii = np.where(values == searchval)[0]
zwroty:
ii ==>array([2, 8])
Może to być znacznie szybsze w przypadku list (tablic) z dużą liczbą elementów w porównaniu do niektórych innych rozwiązań.
[0]jest potrzebna, ponieważ wherezwraca krotkę(array([2, 8], dtype=int64),)
all_id_resp_addresspowinna być np.arraynie list.
listi str, oczywiście zdałeś Falsedo np.where. Gdy np.arrayporównasz z czymś otrzymujesz tablicę wartości boolowskich. Następnie np.whereznajduje pozycje wszystkich Truewartości tej tablicy.
Rozwiązanie wykorzystujące list.index:
def indices(lst, element):
result = []
offset = -1
while True:
try:
offset = lst.index(element, offset+1)
except ValueError:
return result
result.append(offset)
W enumerateprzypadku dużych list jest znacznie szybszy niż zrozumienie listy. Jest również znacznie wolniejszy niż numpyrozwiązanie, jeśli masz już tablicę, w przeciwnym razie koszt konwersji przewyższa wzrost prędkości (testowany na listach całkowitych zawierających 100, 1000 i 10000 elementów).
UWAGA: Uwaga ostrożna w oparciu o komentarz Chris_Rands: to rozwiązanie jest szybsze niż zrozumienie listy, jeśli wyniki są wystarczająco rzadkie, ale jeśli lista zawiera wiele instancji wyszukiwanego elementu (więcej niż ~ 15% listy , w teście z listą 1000 liczb całkowitych), zrozumienie listy jest szybsze.
timeit.timeitz losowo generowanych list. To ważna kwestia i przypuszczam, że właśnie dlatego pytasz. W tym czasie nie przyszło mi to do głowy, ale przyrosty prędkości są prawdziwe tylko wtedy, gdy wyniki są wystarczająco rzadkie. Właśnie przetestowałem z listą pełną elementu do wyszukania, i jest to znacznie wolniejsze niż zrozumienie listy.
more_itertools.locate znajduje indeksy dla wszystkich przedmiotów, które spełniają warunek.
from more_itertools import locate
list(locate([0, 1, 1, 0, 1, 0, 0]))
# [1, 2, 4]
list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b'))
# [1, 3]
more_itertoolsto biblioteka innej firmy > pip install more_itertools.
conda installostatnio stał się bardzo niestabilny w działaniu)
Jeszcze jedno rozwiązanie (przepraszam, jeśli duplikaty) dla wszystkich wystąpień:
values = [1,2,3,1,2,4,5,6,3,2,1]
map(lambda val: (val, [i for i in xrange(len(values)) if values[i] == val]), values)
Lub użyj range(python 3):
l=[i for i in range(len(lst)) if lst[i]=='something...']
Dla (python 2):
l=[i for i in xrange(len(lst)) if lst[i]=='something...']
A następnie (oba przypadki):
print(l)
Jest zgodnie z oczekiwaniami.
Używanie filter () w python2.
>>> q = ['Yeehaw', 'Yeehaw', 'Googol', 'B9', 'Googol', 'NSM', 'B9', 'NSM', 'Dont Ask', 'Googol']
>>> filter(lambda i: q[i]=="Googol", range(len(q)))
[2, 4, 9]
Możesz utworzyć defaultdict
from collections import defaultdict
d1 = defaultdict(int) # defaults to 0 values for keys
unq = set(lst1) # lst1 = [1, 2, 2, 3, 4, 1, 2, 7]
for each in unq:
d1[each] = lst1.count(each)
else:
print(d1)
Za pomocą enumerate (alist) możesz zapisać pierwszy element (n), który jest indeksem listy, gdy element x jest równy temu, czego szukasz.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Ta funkcja przyjmuje argument i listę jako argumenty i zwraca pozycję elementu na liście, jak widzieliśmy wcześniej.
def indexlist(item2find, list_or_string):
"Returns all indexes of an item in a list or a string"
return [n for n,item in enumerate(list_or_string) if item==item2find]
print(indexlist("1", "010101010"))
Wynik
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Wynik:
0
4
for-loop:enumeratei lista są bardziej wydajne i pytoniczne, jednak odpowiedź ta jest skierowana do studentów, którzy mogą nie mieć dostępu do niektórych z tych wbudowanych funkcji .indicesfor i in range(len(x)):, która zasadniczo iteruje przez listę lokalizacji indeksu[0, 1, 2, 3, ..., len(x)-1]i, gdzie x[i]pasuje do value,indices
def get_indices(x: list, value: int) -> list:
indices = list()
for i in range(len(x)):
if x[i] == value:
indices.append(i)
return indices
n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indicessą zaimplementowane z podpowiedziami typu . W tym przypadku lista njest zbiorem ints, dlatego szukamy value, zdefiniowanego również jako int.while-loopi .index:.indexużyj try-exceptdo obsługi błędów, ponieważ ValueErrorwystąpi, jeśli valuenie ma jej na liście.def get_indices(x: list, value: int) -> list:
indices = list()
i = 0
while True:
try:
# find an occurrence of value and update i to that index
i = x.index(value, i)
# add i to the list
indices.append(i)
# advance i by 1
i += 1
except ValueError as e:
break
return indices
print(get_indices(n, -60))
>>> [4, 8, 9]
get_indeicesjest nieco szybsze (~ 15%) niż zwykłe rozumienie listy. Próbuję to rozgryźć.
Jeśli używasz języka Python 2, możesz osiągnąć tę samą funkcjonalność dzięki:
f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))
Gdzie my_listjest lista, dla której chcesz uzyskać indeksy, i valueszukana wartość. Stosowanie:
f(some_list, some_element)
Jeśli potrzebujesz wyszukać wszystkie pozycje elementu między niektórymi indeksami , możesz podać je:
[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]