index()
geeft het eerste voorkomen van een item in een lijst. Is er een handige truc die alle indices in een lijst voor een element retourneert?
Antwoord 1, autoriteit 100%
U kunt een lijstbegrip gebruiken:
indices = [i for i, x in enumerate(my_list) if x == "whatever"]
De iterator enumerate(my_list)
levert paren (index, item)
op voor elk item in de lijst. Door i, x
als lusvariabel doel te gebruiken, worden deze paren uitgepakt in de index i
en het lijstitem x
. We filteren naar alle x
die aan ons criterium voldoen en selecteren de indices i
van deze elementen.
Antwoord 2, autoriteit 20%
Hoewel het geen directe oplossing is voor lijsten, blinkt numpy
echt uit voor dit soort dingen:
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]
retourneert:
ii ==>array([2, 8])
Dit kan aanzienlijk sneller zijn voor lijsten (arrays) met een groot aantal elementen versus sommige van de andere oplossingen.
Antwoord 3, autoriteit 5%
Een oplossing met behulp van 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)
Het is veel sneller dan het begrijpen van lijsten met enumerate
, voor grote lijsten. Het is ook veel langzamer dan de numpy
-oplossing alsje de array al hebt, anders wegen de kosten van het converteren op tegen de snelheidswinst (getest op integer-lijsten met 100, 1000 en 10000 elementen).
OPMERKING:een waarschuwing op basis van de opmerking van Chris_Rands: deze oplossing is sneller dan het begrip van de lijst als de resultaten voldoende schaars zijn, maar als de lijst veel instanties bevat van het element dat wordt gezocht (meer dan ~15% van de lijst, op een test met een lijst van 1000 gehele getallen), is het begrip van de lijst sneller.
Antwoord 4, autoriteit 3%
Wat dacht je van:
In [1]: l=[1,2,3,4,3,2,5,6,7]
In [2]: [i for i,val in enumerate(l) if val==3]
Out[2]: [2, 4]
Antwoord 5
occurrences = lambda s, lst: (i for i,e in enumerate(lst) if e == s)
list(occurrences(1, [1,2,3,1])) # = [0, 3]
Antwoord 6
more_itertools.locate
vindt indices voor alle items die aan een voorwaarde voldoen.
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_itertools
is een externe bibliotheek > pip install more_itertools
.
Antwoord 7
Of gebruik range
(python 3):
l=[i for i in range(len(lst)) if lst[i]=='something...']
Voor (python 2):
l=[i for i in xrange(len(lst)) if lst[i]=='something...']
En dan (beide gevallen):
print(l)
Is zoals verwacht.
Antwoord 8
- Er is een antwoordmet behulp van
np.where
om de indices van een enkele waarde te vinden - De
list
converteren naar eenarray
ennp.where
gebruiken is6.8x
sneller dan welke lijst dan ook -begrip voor het vinden van alle indices van een enkel element. - Snellere oplossingen met
numpy
zijn te vinden in Een lijst krijgen van alle indices van herhaalde elementen in een numpy-array
import numpy as np
import random # to create test list
# create sample list
random.seed(365)
l = [random.choice(['s1', 's2', 's3', 's4']) for _ in range(20)]
# convert the list to an array for use with these numpy methods
a = np.array(l)
# create a dict of each unique entry and the associated indices
idx = {v: np.where(a == v)[0].tolist() for v in np.unique(a)}
# print(idx)
{'s1': [7, 9, 10, 11, 17],
's2': [1, 3, 6, 8, 14, 18, 19],
's3': [0, 2, 13, 16],
's4': [4, 5, 12, 15]}
# find a single element with
idx = np.where(a == 's1')
print(idx)
[out]:
(array([ 7, 9, 10, 11, 17], dtype=int64),)
%timeit
# create 2M element list
random.seed(365)
l = [random.choice(['s1', 's2', 's3', 's4']) for _ in range(2000000)]
# create array
a = np.array(l)
Zoek de indices van één waarde
- Zoek indices van een enkel element in een 2M elementenlijst met 4 unieke elementen
# np.where
%timeit np.where(a == 's1')
[out]:
25.9 ms ± 827 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# list-comprehension
%timeit [i for i, x in enumerate(l) if x == "s1"]
[out]:
175 ms ± 2.73 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# filter
%timeit list(filter(lambda i: a[i]=="s1", range(len(a))))
[out]:
925 ms ± 10.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Zoek de indices van alle waarden
- Vind indexen van alle unieke elementen in een 2M elementenlijst met 4 unieke elementen
# use np.where and np.unique
%timeit {v: np.where(a == v)[0].tolist() for v in np.unique(a)}
[out]:
312 ms ± 9.13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# list comprehension inside dict comprehension
%timeit {req_word: [idx for idx, word in enumerate(a) if word == req_word] for req_word in set(a)}
[out]:
3.72 s ± 21.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Antwoord 9
Nog een oplossing (sorry als het dubbel voorkomt) voor alle gevallen:
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)
Antwoord 10
Alle exemplaren en de positie van een of meer (identieke) items in een lijst ophalen
Met enumerate(alist) kun je het eerste element (n) dat de index van de lijst is, opslaan als het element x gelijk is aan wat je zoekt.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Laten we onze functie findindex maken
Deze functie neemt het item en de lijst als argumenten en retourneert de positie van het item in de lijst, zoals we eerder zagen.
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"))
Uitvoer
[1, 3, 5, 7]
Eenvoudig
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Uitvoer:
0
4
Antwoord 11
Filter() gebruiken in 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]
Antwoord 12
U kunt een standaarddictaat maken
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)
Antwoord 13
Een for-loop
gebruiken:
- Antwoorden met
enumerate
en een lijst begripzijn meer pythonisch, niet noodzakelijkerwijs sneller. Dit antwoord is echter bedoeld voor studenten die sommige van die ingebouwde in functies. - maak een lege lijst,
indices
- maak de lus met
for i in range(len(x)):
, die in wezen door een lijst met indexlocaties loopt[0, 1, 2, 3, ..., len(x)-1]
- voeg in de loop een willekeurige
i
toe, waarbijx[i]
een overeenkomst is metvalue
, aanindices
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]
- De functies,
get_indices
, zijn geïmplementeerd met het type hints. In dit geval is de lijst,n
, een stelint
s, daarom zoeken we naarvalue
, ook gedefinieerd als eenint
.
Een while-loop
en .index
gebruiken:
- Gebruik bij
.index
try-except
voor foutafhandeling, omdat er eenValueError
zal optreden alsvalue
niet in delist
staat .
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]
Antwoord 14
Als je Python 2 gebruikt, kun je hiermee dezelfde functionaliteit bereiken:
f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))
Waarbij my_list
de lijst is waarvan u de indexen wilt krijgen, en value
de gezochte waarde is. Gebruik:
f(some_list, some_element)
Antwoord 15
Als u moet zoeken naar de posities van alle elementen tussen bepaalde indices, kunt u deze aangeven:
[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]
Antwoord 16
Een op dynamische lijst gebaseerde oplossing voor het geval we niet van tevoren weten welk element:
lst = ['to', 'be', 'or', 'not', 'to', 'be']
{req_word: [idx for idx, word in enumerate(lst) if word == req_word] for req_word in set(lst)}
resulteert in:
{'be': [1, 5], 'or': [2], 'to': [0, 4], 'not': [3]}
Je kunt alle andere manieren in dezelfde lijn bedenken, maar met index()
kun je maar één index vinden, hoewel je het nummer van het voorkomen zelf kunt instellen.
Antwoord 17
Hier is een tijdprestatievergelijking tussen het gebruik van np.where
versus list_comprehension
. Het lijkt erop dat np.where
gemiddeld sneller is.
# np.where
start_times = []
end_times = []
for i in range(10000):
start = time.time()
start_times.append(start)
temp_list = np.array([1,2,3,3,5])
ixs = np.where(temp_list==3)[0].tolist()
end = time.time()
end_times.append(end)
print("Took on average {} seconds".format(
np.mean(end_times)-np.mean(start_times)))
Took on average 3.81469726562e-06 seconds
# list_comprehension
start_times = []
end_times = []
for i in range(10000):
start = time.time()
start_times.append(start)
temp_list = np.array([1,2,3,3,5])
ixs = [i for i in range(len(temp_list)) if temp_list[i]==3]
end = time.time()
end_times.append(end)
print("Took on average {} seconds".format(
np.mean(end_times)-np.mean(start_times)))
Took on average 4.05311584473e-06 seconds