Какой самый быстрый способ узнать, существует ли значение в списке (список с миллионами значений в нем) и каков его индекс?
Я знаю, что все значения в списке уникальны, как в этом примере.
Первый метод, который я пробую, - это (3,8 сек в моем реальном коде):
a = [4,2,3,1,5,6]
if a.count(7) == 1:
b=a.index(7)
"Do something with variable b"
Второй метод, который я пытаюсь использовать (в 2 раза быстрее: 1,9 с для моего реального кода):
a = [4,2,3,1,5,6]
try:
b=a.index(7)
except ValueError:
"Do nothing"
else:
"Do something with variable b"
Предлагаемые методы от пользователя Stack Overflow (2,74 с для моего реального кода):
a = [4,2,3,1,5,6]
if 7 in a:
a.index(7)
В моем реальном коде первый метод занимает 3,81 секунды, а второй - 1,88 секунды. Это хорошее улучшение, но:
Я новичок в Python / scripting, и есть ли более быстрый способ сделать то же самое и сэкономить больше времени на обработку?
Более конкретное объяснение для моего приложения:
В Blender API я могу получить доступ к списку частиц:
particles = [1, 2, 3, 4, etc.]
Оттуда я могу получить доступ к местоположению частицы:
particles[x].location = [x,y,z]
И для каждой частицы я проверяю, существует ли сосед, выполняя поиск каждой локации частицы следующим образом:
if [x+1,y,z] in particles.location
"Find the identity of this neighbour particle in x:the particle's index
in the array"
particles.index([x+1,y,z])
источник
bisect
модульОтветы:
Самый простой и быстрый способ сделать это.
Вы также можете рассмотреть возможность использования
set
, но создание этого набора из вашего списка может занять больше времени, чем сэкономит более быстрое тестирование членства. Единственный способ быть уверенным - это хорошо оценивать. (это также зависит от того, какие операции вам требуются)источник
Как утверждают другие,
in
может быть очень медленным для больших списков. Вот несколько сравнений выступлений дляin
,set
иbisect
. Обратите внимание на время (в секундах) в логарифмическом масштабе.Код для тестирования:
источник
import random / import bisect / import matplotlib.pyplot as plt
и затем позвоните:profile()
range()
объект. При использованииvar in [integer list]
посмотрите, может лиrange()
объект моделировать ту же последовательность. Очень близки по производительности к набору, но более лаконичны.Вы можете положить свои вещи в
set
. Набор поисков очень эффективен.Пытаться:
edit В комментарии вы говорите, что хотите получить индекс элемента. К сожалению, наборы не имеют понятия положения элемента. Альтернативой является предварительная сортировка списка, а затем использование бинарного поиска каждый раз, когда вам нужно найти элемент.
источник
Применение
Я считаю, что это самый быстрый способ узнать, находится ли выбранное значение в массиве.
источник
return 'a' in a
?o='--skip'; o in ("--skip-ias"); # returns True !
in
оператор работает так же, чтобы проверить членство в подстроке. Запутанная часть здесь, вероятно,("hello")
состоит в том, что это не кортеж с одним значением, а("hello",)
запятая имеет значение.o in ("--skip-ias",)
это ,False
как ожидалось.Это будет хорошей идеей, только если a не изменится, и, таким образом, мы можем выполнить часть dict () один раз, а затем использовать ее повторно. Если что-то изменилось, пожалуйста, предоставьте более подробную информацию о том, что вы делаете.
источник
Первоначальный вопрос был:
Таким образом, есть две вещи, которые нужно найти:
Для этого я изменил код @xslittlegrass для вычисления индексов во всех случаях и добавил дополнительный метод.
Результаты
Методы:
Результаты показывают, что метод 5 является самым быстрым.
Интересно, что методы try и set эквивалентны по времени.
Тестовый код
источник
Похоже, что ваше приложение может получить преимущество от использования структуры данных Bloom Filter.
Короче говоря, просмотр фильтра Блума может очень быстро сказать вам, если значение ОПРЕДЕЛЕННО НЕ присутствует в наборе. В противном случае вы можете выполнить поиск медленнее, чтобы получить индекс значения, которое МОЖЕТ БЫТЬ в списке. Поэтому, если ваше приложение имеет тенденцию получать результат «не найден» гораздо чаще, чем результат «найден», вы можете ускорить процесс, добавив фильтр Блума.
Для получения более подробной информации Википедия предоставляет хороший обзор того, как работают фильтры Bloom, а веб-поиск «библиотеки фильтров Python Bloom» предоставит как минимум пару полезных реализаций.
источник
Имейте в виду, что
in
оператор проверяет не только равенства (==
), но и идентичности (is
),in
логика дляlist
s примерно эквивалентна следующему (на самом деле он написан на C, а не на Python, по крайней мере в CPython):В большинстве случаев эта деталь не имеет значения, но в некоторых случаях она может удивить новичка в Python, например,
numpy.NAN
необычным свойством быть не равным себе :Чтобы различать эти необычные случаи, вы можете использовать
any()
как:Обратите внимание
in
логика дляlist
s сany()
будет:Тем не менее, я должен подчеркнуть, что это крайний случай, и в подавляющем большинстве случаев
in
оператор высоко оптимизирован и, разумеется, именно то, что вы хотите (с помощьюlist
илиset
).источник
Или используйте
__contains__
:Демо-версия:
источник
Решение @Winston Ewert дает большое ускорение для очень больших списков, но этот ответ на стекопоток указывает, что конструкция try: / exception: / else: будет замедлена, если часто достигается ветвь exc. Альтернативой является использование
.get()
метода для диктовки:.get(key, default)
Метод только для случая , когда вы не можете гарантировать ключ будет в Словаре. Если ключ находится присутствует, она возвращает значение (как былоdict[key]
), но когда это не так ,.get()
возвращает ваше значение по умолчанию (здесьNone
). В этом случае необходимо убедиться, что выбранное значение по умолчанию не будетa
.источник
Это не код, а алгоритм очень быстрого поиска.
Если ваш список и значение, которое вы ищете, все числа, это довольно просто. Если строки: посмотрите внизу:
Если вам также нужна исходная позиция вашего номера, найдите ее во втором столбце индекса.
Если ваш список не состоит из чисел, метод все еще работает и будет самым быстрым, но вам может потребоваться определить функцию, которая может сравнивать / упорядочивать строки.
Конечно, это требует вложений метода sorted (), но если вы продолжаете использовать один и тот же список для проверки, это может стоить того.
источник
Поскольку вопрос не всегда следует понимать как самый быстрый технический способ - я всегда предлагаю самый простой и быстрый способ понять / написать: понимание списка, однострочник
У меня был список
list_to_search_in
всех элементов, и я хотел вернуть индексы элементов вlist_from_which_to_search
.Это возвращает индексы в хорошем списке.
Есть и другие способы проверить эту проблему - однако понимание списка достаточно быстро, добавляя факт написания достаточно быстро, чтобы решить проблему.
источник
Для меня это было 0,030 с (реальное), 0,026 с (пользователь) и 0,004 с (sys).
источник
Код для проверки наличия двух элементов в массиве, произведение которых равно k:
источник