Меня немного смущает этот вопрос: хотите ли вы искать элемент рекурсивно во всех уровнях многомерного списка или вы хотите искать только вхождения в верхнем уровне списка?
Андерсон Грин
22
По моему мнению, должен быть метод списка, который делает именно это.
otocan
Ответы:
546
Вы можете использовать понимание списка:
indices =[i for i, x in enumerate(my_list)if x =="whatever"]
На старых питонах используйте filter () для практически такой же функциональности.
Глено
44
Список понимания появился в Python на 2,0, enumerateна 2,3. Так что да, если ваш Python древний, используйте filter().
Стивен Румбальски
2
Этот метод не находит все вхождения элемента в многомерном массиве. Например, print([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])возвращает []вместо [[0, 1], [0, 0], [1, 1]].
Андерсон Грин
10
@AndersonGreen: термин «многомерный массив» предполагает структуру данных, которая гарантированно будет иметь одинаковый размер по каждой из своих осей. Там нет такой структуры данных в простом Python. Есть списки списков, но они сильно отличаются от «многомерных массивов». Если вы хотите последнее, вам следует рассмотреть возможность использования NumPy, который позволяет вам делать такие вещи, как (a == 1).nonzero()для массива NumPy a.
Свен Марнах
2
@MadmanLee Если вы хотите что-то быстрое, используйте NumPy. Смотрите ответ Джош Адель
Георгий
117
Хотя это не решение для списков напрямую, на 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] в конце преобразует массив в строку. Мне любопытно, почему вы решили это сделать.
Амелия
5
@amelia [0]необходим, потому что whereвозвращает кортеж(array([2, 8], dtype=int64),)
Winand
1
Привет @Win, и я вставил [0], но все еще получаю обе части. Вот мой код: (nrg.local_logs.all_id_resp_address - список) мне, что я сделал не так
Томер
2
@Tomer первую очередь all_id_resp_addressдолжно быть np.arrayне list.
Winand
1
@ Томер, который вы пытались сравнить, listи str, очевидно, вы перешли Falseк np.where. Когда вы сравниваете np.arrayс чем-л. вы получаете массив логических значений. Затем np.whereнаходит позиции всех Trueзначений этого массива.
Winand
29
Решение с использованием list.index:
def indices(lst, element):
result =[]
offset =-1whileTrue:try:
offset = lst.index(element, offset+1)exceptValueError:return result
result.append(offset)
Это намного быстрее, чем понимание enumerateсписков, для больших списков. Это также намного медленнее, чем numpyрешение, если у вас уже есть массив, в противном случае стоимость преобразования перевешивает выигрыш в скорости (проверено на целочисленных списках с 100, 1000 и 10000 элементов).
ПРИМЕЧАНИЕ: предостережение, основанное на комментарии Chris_Rands: это решение быстрее, чем понимание списка, если результаты достаточно скудны, но если в списке много экземпляров искомого элемента (более ~ 15% списка в тесте со списком из 1000 целых чисел) понимание списка происходит быстрее.
Вы говорите, что это быстрее, чем список композиций, можете ли вы показать свои сроки, которые демонстрируют это?
Chris_Rands
5
Это было давно, я, вероятно, использовал timeit.timeitсо случайно сгенерированными списками. Это важный момент, и я полагаю, что это может быть то, почему вы спрашиваете. В то время мне это не приходило в голову, но прирост скорости верен только в том случае, если результаты достаточно скудны. Я только что проверил со списком, полным элемента для поиска, и это намного медленнее, чем понимание списка.
Пауло Алмейда
18
Как насчет:
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]
Получение всех вхождений и положения одного или нескольких (идентичных) элементов в списке
С помощью 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]>>>
Давайте сделаем нашу функцию findindex
Эта функция принимает элемент и список в качестве аргументов и возвращает позицию элемента в списке, как мы видели ранее.
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)
Этот ответ мне было проще всего реализовать в моем существующем коде.
Райан Харрис
2
Используя 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- это набор ints, поэтому мы ищем value, также определяемый как int.
Используя while-loopи .index:
С .index, используйте try-exceptдля обработки ошибок, потому ValueErrorчто произойдет, если valueнет в списке.
def get_indices(x: list, value: int)-> list:
indices = list()
i =0whileTrue: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 +=1exceptValueErroras e:breakreturn indices
print(get_indices(n,-60))>>>[4,8,9]
Ответы:
Вы можете использовать понимание списка:
источник
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()
для массива NumPya
.Хотя это не решение для списков напрямую, на
numpy
самом деле это хорошо для такого рода вещей:возвращает:
Это может быть значительно быстрее для списков (массивов) с большим количеством элементов по сравнению с некоторыми другими решениями.
источник
[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
:Это намного быстрее, чем понимание
enumerate
списков, для больших списков. Это также намного медленнее, чемnumpy
решение, если у вас уже есть массив, в противном случае стоимость преобразования перевешивает выигрыш в скорости (проверено на целочисленных списках с 100, 1000 и 10000 элементов).ПРИМЕЧАНИЕ: предостережение, основанное на комментарии Chris_Rands: это решение быстрее, чем понимание списка, если результаты достаточно скудны, но если в списке много экземпляров искомого элемента (более ~ 15% списка в тесте со списком из 1000 целых чисел) понимание списка происходит быстрее.
источник
timeit.timeit
со случайно сгенерированными списками. Это важный момент, и я полагаю, что это может быть то, почему вы спрашиваете. В то время мне это не приходило в голову, но прирост скорости верен только в том случае, если результаты достаточно скудны. Я только что проверил со списком, полным элемента для поиска, и это намного медленнее, чем понимание списка.Как насчет:
источник
источник
more_itertools.locate
находит индексы для всех предметов, которые удовлетворяют условию.more_itertools
это сторонняя библиотека> pip install more_itertools
.источник
conda install
в последнее время он стал очень нестабильным в производительности)Еще одно решение (извините, если дублирует) для всех случаев:
источник
Или используйте
range
(python 3):Для (Python 2):
И тогда (оба случая):
Как и ожидалось.
источник
Использование filter () в python2.
источник
Вы можете создать defaultdict
источник
Получение всех вхождений и положения одного или нескольких (идентичных) элементов в списке
С помощью enumerate (alist) вы можете сохранить первый элемент (n), который является индексом списка, когда элемент x равен тому, что вы ищете.
Давайте сделаем нашу функцию findindex
Эта функция принимает элемент и список в качестве аргументов и возвращает позицию элемента в списке, как мы видели ранее.
Вывод
просто
Вывод:
источник
Используя
for-loop
:enumerate
и список понимание являются более эффективными и вещий, однако, этот ответ направлен на студентов , которые не могут быть разрешено использовать некоторые из этих встроенных функций .indices
for i in range(len(x)):
, который по существу перебирает список местоположений индекса[0, 1, 2, 3, ..., len(x)-1]
i
, гдеx[i]
совпадаетvalue
,indices
x[i]
получает доступ к списку по индексуget_indices
реализованы с подсказками типов . В этом случае списокn
- это наборint
s, поэтому мы ищемvalue
, также определяемый какint
.Используя
while-loop
и.index
:.index
, используйтеtry-except
для обработки ошибок, потомуValueError
что произойдет, еслиvalue
нет в списке.источник
get_indeices
немного быстрее (~ 15%), чем обычное понимание списка. Я пытаюсь понять это.Если вы используете Python 2, вы можете достичь той же функциональности с помощью этого:
Где
my_list
находится список, из которого вы хотите получить индексы, иvalue
это искомое значение. Применение:источник
Если вам нужно найти все позиции элемента между определенными индексами , вы можете указать их:
источник