index()
просто даст первое вхождение элемента в списке. Есть ли хитрый трюк, который возвращает все индексы в списке?
index()
просто даст первое вхождение элемента в списке. Есть ли хитрый трюк, который возвращает все индексы в списке?
Ответы:
Вы можете использовать понимание списка:
indices = [i for i, x in enumerate(my_list) if x == "whatever"]
enumerate
на 2,3. Так что да, если ваш Python древний, используйте filter()
.
print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])
возвращает []
вместо [[0, 1], [0, 0], [1, 1]]
.
(a == 1).nonzero()
для массива NumPy a
.
Хотя это не решение для списков напрямую, на numpy
самом деле это хорошо для такого рода вещей:
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]
возвращает:
ii ==>array([2, 8])
Это может быть значительно быстрее для списков (массивов) с большим количеством элементов по сравнению с некоторыми другими решениями.
[0]
необходим, потому что where
возвращает кортеж(array([2, 8], dtype=int64),)
all_id_resp_address
должно быть np.array
не list
.
list
и str
, очевидно, вы перешли False
к np.where
. Когда вы сравниваете np.array
с чем-л. вы получаете массив логических значений. Затем np.where
находит позиции всех True
значений этого массива.
Решение с использованием 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)
Это намного быстрее, чем понимание enumerate
списков, для больших списков. Это также намного медленнее, чем numpy
решение, если у вас уже есть массив, в противном случае стоимость преобразования перевешивает выигрыш в скорости (проверено на целочисленных списках с 100, 1000 и 10000 элементов).
ПРИМЕЧАНИЕ: предостережение, основанное на комментарии Chris_Rands: это решение быстрее, чем понимание списка, если результаты достаточно скудны, но если в списке много экземпляров искомого элемента (более ~ 15% списка в тесте со списком из 1000 целых чисел) понимание списка происходит быстрее.
timeit.timeit
со случайно сгенерированными списками. Это важный момент, и я полагаю, что это может быть то, почему вы спрашиваете. В то время мне это не приходило в голову, но прирост скорости верен только в том случае, если результаты достаточно скудны. Я только что проверил со списком, полным элемента для поиска, и это намного медленнее, чем понимание списка.
more_itertools.locate
находит индексы для всех предметов, которые удовлетворяют условию.
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
это сторонняя библиотека > pip install more_itertools
.
conda install
в последнее время он стал очень нестабильным в производительности)
Еще одно решение (извините, если дублирует) для всех случаев:
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)
Или используйте range
(python 3):
l=[i for i in range(len(lst)) if lst[i]=='something...']
Для (Python 2):
l=[i for i in xrange(len(lst)) if lst[i]=='something...']
И тогда (оба случая):
print(l)
Как и ожидалось.
Использование filter () в 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]
Вы можете создать 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)
С помощью enumerate (alist) вы можете сохранить первый элемент (n), который является индексом списка, когда элемент x равен тому, что вы ищете.
>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>
Эта функция принимает элемент и список в качестве аргументов и возвращает позицию элемента в списке, как мы видели ранее.
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"))
Вывод
[1, 3, 5, 7]
for n, i in enumerate([1, 2, 3, 4, 1]):
if i == 1:
print(n)
Вывод:
0
4
for-loop
:enumerate
и список понимание являются более эффективными и вещий, однако, этот ответ направлен на студентов , которые не могут быть разрешено использовать некоторые из этих встроенных функций .indices
for i in range(len(x)):
, который по существу перебирает список местоположений индекса[0, 1, 2, 3, ..., len(x)-1]
i
, где x[i]
совпадает 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_indices
реализованы с подсказками типов . В этом случае список n
- это набор int
s, поэтому мы ищем value
, также определяемый как int
.while-loop
и .index
:.index
, используйте try-except
для обработки ошибок, потому ValueError
что произойдет, если value
нет в списке.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_indeices
немного быстрее (~ 15%), чем обычное понимание списка. Я пытаюсь понять это.
Если вы используете Python 2, вы можете достичь той же функциональности с помощью этого:
f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))
Где my_list
находится список, из которого вы хотите получить индексы, и value
это искомое значение. Применение:
f(some_list, some_element)
Если вам нужно найти все позиции элемента между определенными индексами , вы можете указать их:
[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]