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и список понимание являются более эффективными и вещий, однако, этот ответ направлен на студентов , которые не могут быть разрешено использовать некоторые из этих встроенных функций .indicesfor 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- это набор ints, поэтому мы ищем 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]