На чтение 4 мин Просмотров 5.3к. Опубликовано 03.03.2023
Содержание
- Введение
- Поиск методом count
- Поиск при помощи цикла for
- Поиск с использованием оператора in
- В одну строку
- Поиск с помощью лямбда функции
- Поиск с помощью функции any()
- Заключение
Введение
В ходе статьи рассмотрим 5 способов поиска элемента в списке Python.
Поиск методом count
Метод count() возвращает вхождение указанного элемента в последовательность. Создадим список разных цветов, чтобы в нём производить поиск:
colors = ['black', 'yellow', 'grey', 'brown']
Зададим условие, что если в списке colors присутствует элемент ‘yellow’, то в консоль будет выведено сообщение, что элемент присутствует. Если же условие не сработало, то сработает else, и будет выведена надпись, что элемента отсутствует в списке:
colors = ['black', 'yellow', 'grey', 'brown']
if colors.count('yellow'):
print('Элемент присутствует в списке!')
else:
print('Элемент отсутствует в списке!')
# Вывод: Элемент присутствует в списке!
Поиск при помощи цикла for
Создадим цикл, в котором будем перебирать элементы из списка colors. Внутри цикла зададим условие, что если во время итерации color приняла значение ‘yellow’, то элемент присутствует:
colors = ['black', 'yellow', 'grey', 'brown']
for color in colors:
if color == 'yellow':
print('Элемент присутствует в списке!')
# Вывод: Элемент присутствует в списке!
Поиск с использованием оператора in
Оператор in предназначен для проверки наличия элемента в последовательности, и возвращает либо True, либо False.
Зададим условие, в котором если ‘yellow’ присутствует в списке, то выводится соответствующее сообщение:
colors = ['black', 'yellow', 'grey', 'brown']
if 'yellow' in colors:
print('Элемент присутствует в списке!')
else:
print('Элемент отсутствует в списке!')
# Вывод: Элемент присутствует в списке!
В одну строку
Также можно найти элемент в списке при помощи оператора in всего в одну строку:
colors = ['black', 'yellow', 'grey', 'brown']
print('Элемент присутствует в списке!') if 'yellow' in colors else print('Элемент отсутствует в списке!')
# Вывод: Элемент присутствует в списке!
Или можно ещё вот так:
colors = ['black', 'yellow', 'grey', 'brown']
if 'yellow' in colors: print('Элемент присутствует в списке!')
# Вывод: Элемент присутствует в списке!
Поиск с помощью лямбда функции
В переменную filtering будет сохранён итоговый результат. Обернём результат в список (list()), т.к. метода filter() возвращает объект filter. Отфильтруем все элементы списка, и оставим только искомый, если он конечно присутствует:
colors = ['black', 'yellow', 'grey', 'brown']
filtering = list(filter(lambda x: 'yellow' in x, colors))
Итак, если искомый элемент находился в списке, то он сохранился в переменную filtering. Создадим условие, что если переменная filtering не пустая, то выведем сообщение о присутствии элемента в списке. Иначе – отсутствии:
colors = ['black', 'yellow', 'grey', 'brown']
filtering = list(filter(lambda x: 'yellow' in x, colors))
if filtering:
print('Элемент присутствует в списке!')
else:
print('Элемент отсутствует в списке!')
# Вывод: Элемент присутствует в списке!
Поиск с помощью функции any()
Функция any принимает в качестве аргумента итерабельный объект, и возвращает True, если хотя бы один элемент равен True, иначе будет возвращено False.
Создадим условие, что если функция any() вернёт True, то элемент присутствует:
colors = ['black', 'yellow', 'grey', 'brown']
if any(color in 'yellow' for color in colors):
print('Элемент присутствует в списке!')
else:
print('Элемент отсутствует в списке!')
# Вывод: Элемент присутствует в списке!
Внутри функции any() при помощи цикла производится проверка присутствия элемента в списке.
Заключение
В ходе статьи мы с Вами разобрали целых 5 способов поиска элемента в списке Python. Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂
Let’s assume I’m creating a simple class to work similar to a C-style struct, to just hold data elements. I’m trying to figure out how to search a list of objects for objects with an attribute equaling a certain value. Below is a trivial example to illustrate what I’m trying to do.
For instance:
class Data:
pass
myList = []
for i in range(20):
data = Data()
data.n = i
data.n_squared = i * i
myList.append(data)
How would I go about searching the myList list to determine if it contains an element with n == 5?
I’ve been Googling and searching the Python docs, and I think I might be able to do this with a list comprehension, but I’m not sure. I might add that I’m having to use Python 2.4.3 by the way, so any new gee-whiz 2.6 or 3.x features aren’t available to me.
DevPlayer
5,3431 gold badge25 silver badges20 bronze badges
asked Feb 28, 2009 at 18:06
1
You can get a list of all matching elements with a list comprehension:
[x for x in myList if x.n == 30] # list of all elements with .n==30
If you simply want to determine if the list contains any element that matches and do it (relatively) efficiently, you can do
def contains(list, filter):
for x in list:
if filter(x):
return True
return False
if contains(myList, lambda x: x.n == 3) # True if any element has .n==3
# do stuff
Ali Afshar
40.8k12 gold badges94 silver badges109 bronze badges
answered Feb 28, 2009 at 18:11
Adam RosenfieldAdam Rosenfield
388k96 gold badges512 silver badges586 bronze badges
3
Simple, Elegant, and Powerful:
A generator expression in conjuction with a builtin… (python 2.5+)
any(x for x in mylist if x.n == 10)
Uses the Python any() builtin, which is defined as follows:
any(iterable)
->
Return True if any element of the iterable is true. Equivalent to:
def any(iterable):
for element in iterable:
if element:
return True
return False
h3xStream
6,2032 gold badges46 silver badges57 bronze badges
answered Feb 28, 2009 at 20:15
gahooagahooa
130k12 gold badges97 silver badges100 bronze badges
3
Just for completeness, let’s not forget the Simplest Thing That Could Possibly Work:
for i in list:
if i.n == 5:
# do something with it
print "YAY! Found one!"
answered Feb 28, 2009 at 18:20
Charlie MartinCharlie Martin
110k24 gold badges193 silver badges260 bronze badges
0
[x for x in myList if x.n == 30] # list of all matches
[x.n_squared for x in myList if x.n == 30] # property of matches
any(x.n == 30 for x in myList) # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30] # indices of all matches
def first(iterable, default=None):
for item in iterable:
return item
return default
first(x for x in myList if x.n == 30) # the first match, if any
answered Feb 28, 2009 at 18:19
Markus JarderotMarkus Jarderot
86.4k21 gold badges136 silver badges138 bronze badges
2
filter(lambda x: x.n == 5, myList)
answered Feb 28, 2009 at 18:22
vartecvartec
130k36 gold badges217 silver badges244 bronze badges
3
You can use in to look for an item in a collection, and a list comprehension to extract the field you are interested in. This (works for lists, sets, tuples, and anything that defines __contains__ or __getitem__).
if 5 in [data.n for data in myList]:
print "Found it"
See also:
- Contains Method
- In operation
answered Feb 28, 2009 at 18:23
Tom DunhamTom Dunham
5,7592 gold badges30 silver badges27 bronze badges
Another way you could do it is using the next() function.
matched_obj = next(x for x in list if x.n == 10)
m0j0
3,4445 gold badges27 silver badges33 bronze badges
answered Jun 16, 2020 at 6:01
SEMICSSEMICS
1713 silver badges4 bronze badges
You should add a __eq__ and a __hash__ method to your Data class, it could check if the __dict__ attributes are equal (same properties) and then if their values are equal, too.
If you did that, you can use
test = Data()
test.n = 5
found = test in myList
The in keyword checks if test is in myList.
If you only want to a a n property in Data you could use:
class Data(object):
__slots__ = ['n']
def __init__(self, n):
self.n = n
def __eq__(self, other):
if not isinstance(other, Data):
return False
if self.n != other.n:
return False
return True
def __hash__(self):
return self.n
myList = [ Data(1), Data(2), Data(3) ]
Data(2) in myList #==> True
Data(5) in myList #==> False
answered Feb 28, 2009 at 18:10
Johannes WeissJohannes Weiss
52.2k16 gold badges102 silver badges136 bronze badges
Consider using a dictionary:
myDict = {}
for i in range(20):
myDict[i] = i * i
print(5 in myDict)
answered Mar 1, 2009 at 1:14
dan-gphdan-gph
16.2k12 gold badges61 silver badges79 bronze badges
2
Use the following list comprehension in combination with the index method:
data_n = 30
j = [data.n for data in mylist].index(data_n)
print(mylist[j].data.n == data_n)
Tomerikoo
18.1k16 gold badges45 silver badges60 bronze badges
answered Apr 18, 2021 at 18:55
Введение
Поиск информации, хранящейся в различных структурах данных, является важной частью практически каждого приложения.
Существует множество различных алгоритмов, которые можно использовать для поиска. Каждый из них имеет разные реализации и напрямую зависит от структуры данных, для которой он реализован.
Умение выбрать нужный алгоритм для конкретной задачи является ключевым навыком для разработчиков. Именно правильно подобранный алгоритм отличает быстрое, надежное и стабильное приложение от приложения, которое падает от простого запроса.
В этой статье:
- Операторы членства (Membership Operators)
- Линейный поиск
- Бинарный поиск
- Улучшенный линейный поиск — Jump Search
- Поиск Фибоначчи
- Экспоненциальный поиск
- Интерполяционный поиск
Операторы членства (Membership Operators)
Алгоритмы развиваются и оптимизируются в результате постоянной эволюции и необходимости находить наиболее эффективные решения для основных проблем в различных областях.
Одной из наиболее распространенных проблем в области компьютерных наук является поиск в коллекции и определение того, присутствует ли данный объект в коллекции или нет.
Почти каждый язык программирования имеет свою собственную реализацию базового алгоритма поиска. Обычно — в виде функции, которая возвращает логическое значение True или False, когда элемент найден в данной коллекции элементов.
В Python самый простой способ поиска объекта — использовать операторы членства. Их название связано с тем, что они позволяют нам определить, является ли данный объект членом коллекции.
Эти операторы могут использоваться с любой итерируемой структурой данных в Python, включая строки, списки и кортежи.
in— возвращаетTrue, если данный элемент присутствует в структуре данных.not in— возвращаетTrue, если данный элемент не присутствует в структуре данных.
>>> 'apple' in ['orange', 'apple', 'grape'] True >>> 't' in 'pythonist' True >>> 'q' in 'pythonist' False >>> 'q' not in 'pythonist' True
Операторов членства достаточно, если нам нужно только определить, существует ли подстрока в данной строке, или пересекаются ли две строки, два списка или кортежа с точки зрения содержащихся в них объектов.
В большинстве случаев помимо определения, наличествует ли элемент в последовательности, нам нужна еще и позиция (индекс) элемента. Используя операторы членства, мы не можем получить ее.
Существует множество алгоритмов поиска, которые не зависят от встроенных операторов и могут использоваться для более быстрого и/или эффективного поиска значений. Кроме того, они могут дать больше информации (например, о позиции элемента в коллекции), а не просто определить, есть ли в коллекции этот элемент.
Линейный поиск
Линейный поиск — это один из самых простых и понятных алгоритмов поиска. Мы можем думать о нем как о расширенной версии нашей собственной реализации оператора in в Python.
Суть алгоритма заключается в том, чтобы перебрать массив и вернуть индекс первого вхождения элемента, когда он найден:
def LinearSearch(lys, element):
for i in range (len(lys)):
if lys[i] == element:
return i
return -1
Итак, если мы используем функцию для вычисления:
>>> print(LinearSearch([1,2,3,4,5,2,1], 2))
То получим следующий результат:
1
Это индекс первого вхождения искомого элемента, учитывая, что нумерация элементов в Python начинается с нуля.
Временная сложность линейного поиска равна O(n). Это означает, что время, необходимое для выполнения, увеличивается с увеличением количества элементов в нашем входном списке lys.
Линейный поиск не часто используется на практике, потому что такая же эффективность может быть достигнута с помощью встроенных методов или существующих операторов. К тому же, он не такой быстрый и эффективный, как другие алгоритмы поиска.
Линейный поиск хорошо подходит для тех случаев, когда нам нужно найти первое вхождение элемента в несортированной коллекции. Это связано с тем, что он не требует сортировки коллекции перед поиском (в отличие от большинства других алгоритмов поиска).
Бинарный поиск
Бинарный поиск работает по принципу «разделяй и властвуй». Он быстрее, чем линейный поиск, но требует, чтобы массив был отсортирован перед выполнением алгоритма.
Предполагая, что мы ищем значение val в отсортированном массиве, алгоритм сравнивает val со значением среднего элемента массива, который мы будем называть mid.
- Если
mid— это тот элемент, который мы ищем (в лучшем случае), мы возвращаем его индекс. - Если нет, мы определяем, в какой половине массива мы будем искать
valдальше, основываясь на том, меньше или больше значениеvalзначенияmid, и отбрасываем вторую половину массива. - Затем мы рекурсивно или итеративно выполняем те же шаги, выбирая новое значение для
mid, сравнивая его сvalи отбрасывая половину массива на каждой итерации алгоритма.
Алгоритм бинарного поиска можно написать как рекурсивно, так и итеративно. В Python рекурсия обычно медленнее, потому что она требует выделения новых кадров стека.
Поскольку хороший алгоритм поиска должен быть максимально быстрым и точным, давайте рассмотрим итеративную реализацию бинарного поиска:
def BinarySearch(lys, val):
first = 0
last = len(lys)-1
index = -1
while (first <= last) and (index == -1):
mid = (first+last)//2
if lys[mid] == val:
index = mid
else:
if val<lys[mid]:
last = mid -1
else:
first = mid +1
return index
Если мы используем функцию для вычисления:
>>> BinarySearch([10,20,30,40,50], 20)
То получим следующий результат, являющийся индексом искомого значения:
1
На каждой итерации алгоритм выполняет одно из следующих действий:
- Возврат индекса текущего элемента.
- Поиск в левой половине массива.
- Поиск в правой половине массива.
Мы можем выбрать только одно действие на каждой итерации. Также на каждой итерации наш массив делится на две части. Из-за этого временная сложность двоичного поиска равна O(log n).
Одним из недостатков бинарного поиска является то, что если в массиве имеется несколько вхождений элемента, он возвращает индекс не первого элемента, а ближайшего к середине:
>>> print(BinarySearch([4,4,4,4,4], 4))
После выполнения этого фрагмента кода будет возвращен индекс среднего элемента:
2
Для сравнения: выполнение линейного поиска по тому же массиву вернет индекс первого элемента:
0
Однако мы не можем категорически утверждать, что двоичный поиск не работает, если массив содержит дубликаты. Он может работать так же, как линейный поиск, и в некоторых случаях возвращать первое вхождение элемента. Например:
>>> print(BinarySearch([1,2,3,4,4,4,5], 4)) 3
Бинарный поиск довольно часто используется на практике, потому что он эффективен и быстр по сравнению с линейным поиском. Однако у него есть некоторые недостатки, такие как зависимость от оператора //. Существует много других алгоритмов поиска, работающих по принципу «разделяй и властвуй», которые являются производными от бинарного поиска. Некоторые из них мы рассмотрим далее.
Jump Search
Jump Search похож на бинарный поиск тем, что он также работает с отсортированным массивом и использует аналогичный подход «разделяй и властвуй» для поиска по нему.
Его можно классифицировать как усовершенствованный алгоритм линейного поиска, поскольку он зависит от линейного поиска для выполнения фактического сравнения при поиске значения.
В заданном отсортированном массиве мы ищем не постепенно по элементам массива, а скачкообразно. Если у нас есть размер прыжка, то наш алгоритм будет рассматривать элементы входного списка lys в следующем порядке: lys[0], lys[0+jump], lys[0+2jump], lys[0+3jump] и так далее.
С каждым прыжком мы сохраняем предыдущее значение и его индекс. Когда мы находим множество значений (блок), где lys[i] < element < lys[i + jump], мы выполняем линейный поиск с lys[i] в качестве самого левого элемента и lys[i + jump] в качестве самого правого элемента в нашем множестве:
import math
def JumpSearch (lys, val):
length = len(lys)
jump = int(math.sqrt(length))
left, right = 0, 0
while left < length and lys[left] <= val:
right = min(length - 1, left + jump)
if lys[left] <= val and lys[right] >= val:
break
left += jump;
if left >= length or lys[left] > val:
return -1
right = min(length - 1, right)
i = left
while i <= right and lys[i] <= val:
if lys[i] == val:
return i
i += 1
return -1
Поскольку это сложный алгоритм, давайте рассмотрим пошаговое вычисление для следующего примера:
>>> print(JumpSearch([1,2,3,4,5,6,7,8,9], 5))
- Jump search сначала определит размер прыжка путем вычисления
math.sqrt(len(lys)). Поскольку у нас 9 элементов, размер прыжка будет √9 = 3. - Далее мы вычисляем значение переменной
right. Оно рассчитывается как минимум из двух значений: длины массива минус 1 и значенияleft + jump, которое в нашем случае будет 0 + 3 = 3. Поскольку 3 меньше 8, мы используем 3 в качестве значения переменнойright. - Теперь проверим, находится ли наш искомый элемент 5 между
lys[0]иlys[3]. Поскольку 5 не находится между 1 и 4, мы идем дальше. - Затем мы снова делаем расчеты и проверяем, находится ли наш искомый элемент между
lys[3]иlys[6], где 6 — это 3 + jump. Поскольку 5 находится между 4 и 7, мы выполняем линейный поиск по элементам междуlys[3]иlys[6]и возвращаем индекс нашего элемента:
4
Временная сложность jump search равна O(√n), где √n — размер прыжка, а n — длина списка. Таким образом, с точки зрения эффективности jump search находится между алгоритмами линейного и бинарного поиска.
Единственное наиболее важное преимущество jump search по сравнению с бинарным поиском заключается в том, что он не опирается на оператор деления (/).
В большинстве процессоров использование оператора деления является дорогостоящим по сравнению с другими основными арифметическими операциями (сложение, вычитание и умножение), поскольку реализация алгоритма деления является итеративной.
Стоимость сама по себе очень мала, но когда количество искомых элементов очень велико, а количество необходимых операций деления растет, стоимость может постепенно увеличиваться. Поэтому jump search лучше бинарного поиска, когда в системе имеется большое количество элементов: там даже небольшое увеличение скорости имеет значение.
Чтобы ускорить jump search, мы могли бы использовать бинарный поиск или какой-нибудь другой алгоритм для поиска в блоке вместо использования гораздо более медленного линейного поиска.
Поиск Фибоначчи
Поиск Фибоначчи — это еще один алгоритм «разделяй и властвуй», который имеет сходство как с бинарным поиском, так и с jump search. Он получил свое название потому, что использует числа Фибоначчи для вычисления размера блока или диапазона поиска на каждом шаге.
Числа Фибоначчи — это последовательность чисел 0, 1, 1, 2, 3, 5, 8, 13, 21 …, где каждый элемент является суммой двух предыдущих чисел.
Алгоритм работает с тремя числами Фибоначчи одновременно. Давайте назовем эти три числа fibM, fibM_minus_1 и fibM_minus_2. Где fibM_minus_1 и fibM_minus_2 — это два числа, предшествующих fibM в последовательности:
fibM = fibM_minus_1 + fibM_minus_2
Мы инициализируем значения 0, 1, 1 или первые три числа в последовательности Фибоначчи. Это поможет нам избежать IndexError в случае, когда наш массив lys содержит очень маленькое количество элементов.
Затем мы выбираем наименьшее число последовательности Фибоначчи, которое больше или равно числу элементов в нашем массиве lys, в качестве значения fibM. А два числа Фибоначчи непосредственно перед ним — в качестве значений fibM_minus_1 и fibM_minus_2. Пока в массиве есть элементы и значение fibM больше единицы, мы:
- Сравниваем
valсо значением блока в диапазоне доfibM_minus_2и возвращаем индекс элемента, если он совпадает. - Если значение больше, чем элемент, который мы в данный момент просматриваем, мы перемещаем значения
fibM,fibM_minus_1иfibM_minus_2на два шага вниз в последовательности Фибоначчи и меняем индекс на индекс элемента. - Если значение меньше, чем элемент, который мы в данный момент просматриваем, мы перемещаем значения
fibM,fibM_minus_1иfibM_minus_2на один шаг вниз в последовательности Фибоначчи.
Давайте посмотрим на реализацию этого алгоритма на Python:
def FibonacciSearch(lys, val):
fibM_minus_2 = 0
fibM_minus_1 = 1
fibM = fibM_minus_1 + fibM_minus_2
while (fibM < len(lys)):
fibM_minus_2 = fibM_minus_1
fibM_minus_1 = fibM
fibM = fibM_minus_1 + fibM_minus_2
index = -1;
while (fibM > 1):
i = min(index + fibM_minus_2, (len(lys)-1))
if (lys[i] < val):
fibM = fibM_minus_1
fibM_minus_1 = fibM_minus_2
fibM_minus_2 = fibM - fibM_minus_1
index = i
elif (lys[i] > val):
fibM = fibM_minus_2
fibM_minus_1 = fibM_minus_1 - fibM_minus_2
fibM_minus_2 = fibM - fibM_minus_1
else :
return i
if(fibM_minus_1 and index < (len(lys)-1) and lys[index+1] == val):
return index+1;
return -1
Используем функцию FibonacciSearch для вычисления:
>>> print(FibonacciSearch([1,2,3,4,5,6,7,8,9,10,11], 6))
Давайте посмотрим на пошаговый процесс поиска:
- Присваиваем переменной
fibMнаименьшее число Фибоначчи, которое больше или равно длине списка. В данном случае наименьшее число Фибоначчи, отвечающее нашим требованиям, равно 13. - Значения присваиваются следующим образом:
fibM = 13
fibM_minus_1 = 8
fibM_minus_2 = 5
index = -1
- Далее мы проверяем элемент
lys[4], где 4 — это минимум из двух значений —index + fibM_minus_2(-1+5) и длина массива минус 1 (11-1). Поскольку значениеlys[4]равно 5, что меньше искомого значения, мы перемещаем числа Фибоначчи на один шаг вниз в последовательности, получая следующие значения:
fibM = 8
fibM_minus_1 = 5
fibM_minus_2 = 3
index = 4
- Далее мы проверяем элемент
lys[7], где 7 — это минимум из двух значений:index + fibM_minus_2(4 + 3) и длина массива минус 1 (11-1). Поскольку значениеlys[7]равно 8, что больше искомого значения, мы перемещаем числа Фибоначчи на два шага вниз в последовательности, получая следующие значения:
fibM = 3
fibM_minus_1 = 2
fibM_minus_2 = 1
index = 4
- Затем мы проверяем элемент
lys[5], где 5 — это минимум из двух значений:index + fibM_minus_2(4+1) и длина массива минус 1 (11-1) . Значениеlys[5]равно 6, и это наше искомое значение!
Получаем ожидаемый результат:
5
Временная сложность поиска Фибоначчи равна O(log n). Она такая же, как и у бинарного поиска. Это означает, что алгоритм в большинстве случаев работает быстрее, чем линейный поиск и jump search.
Поиск Фибоначчи можно использовать, когда у нас очень большое количество искомых элементов и мы хотим уменьшить неэффективность, связанную с использованием алгоритма, основанного на операторе деления.
Дополнительным преимуществом использования поиска Фибоначчи является то, что он может вместить входные массивы, которые слишком велики для хранения в кэше процессора или ОЗУ, потому что он ищет элементы с увеличивающимся шагом, а не с фиксированным.
Экспоненциальный поиск
Экспоненциальный поиск — это еще один алгоритм поиска, который может быть достаточно легко реализован на Python, по сравнению с jump search и поиском Фибоначчи, которые немного сложны. Он также известен под названиями galloping search, doubling search и Struzik search.
Экспоненциальный поиск зависит от бинарного поиска для выполнения окончательного сравнения значений. Алгоритм работает следующим образом:
- Определяется диапазон, в котором, скорее всего, будет находиться искомый элемент.
- В этом диапазоне используется двоичный поиск для нахождения индекса элемента.
Реализация алгоритма экспоненциального поиска на Python:
def ExponentialSearch(lys, val):
if lys[0] == val:
return 0
index = 1
while index < len(lys) and lys[index] <= val:
index = index * 2
return BinarySearch( lys[:min(index, len(lys))], val)
Используем функцию, чтобы найти значение:
>>> print(ExponentialSearch([1,2,3,4,5,6,7,8],3))
Рассмотрим работу алгоритма пошагово.
- Проверяем, соответствует ли первый элемент списка искомому значению: поскольку
lys[0]равен 1, а мы ищем 3, мы устанавливаем индекс равным 1 и двигаемся дальше. - Перебираем все элементы в списке, и пока элемент с текущим индексом меньше или равен нашему значению, умножаем значение индекса на 2:
- index = 1,
lys[1]равно 2, что меньше 3, поэтому значение index умножается на 2 и переменнойindexприсваивается значение 2. - index = 2,
lys[2]равно 3, что равно 3, поэтому значениеindexумножается на 2 и переменнойindexприсваивается значение 4. - index = 4,
lys[4]равно 5, что больше 3. Условие выполнения цикла больше не соблюдается и цикл завершает свою работу.
- Затем выполняется двоичный поиск в полученном диапазоне (срезе)
lys[:4]. В Python это означает, что подсписок будет содержать все элементы до 4-го элемента, поэтому мы фактически вызываем функцию следующим образом:
>>> BinarySearch([1,2,3,4], 3)
Функция вернет следующий результат:
2
Этот результат является индексом искомого элемента как в исходном списке, так и в срезе, который мы передаем алгоритму бинарного поиска.
Экспоненциальный поиск выполняется за время O(log i), где i — индекс искомого элемента. В худшем случае временная сложность равна O(log n), когда искомый элемент — это последний элемент в массиве (n — это длина массива).
Экспоненциальный поиск работает лучше, чем бинарный, когда искомый элемент находится ближе к началу массива. На практике мы используем экспоненциальный поиск, поскольку это один из наиболее эффективных алгоритмов поиска в неограниченных или бесконечных массивах.
Интерполяционный поиск
Интерполяционный поиск — это еще один алгоритм «разделяй и властвуй», аналогичный бинарному поиску. В отличие от бинарного поиска, он не всегда начинает поиск с середины. Интерполяционный поиск вычисляет вероятную позицию искомого элемента по формуле:
index = low + [(val-lys[low])*(high-low) / (lys[high]-lys[low])]
В этой формуле используются следующие переменные:
- lys — наш входной массив.
- val — искомый элемент.
- index — вероятный индекс искомого элемента. Он вычисляется как более высокое значение, когда значение val ближе по значению к элементу в конце массива (
lys[high]), и более низкое, когда значение val ближе по значению к элементу в начале массива (lys[low]). - low — начальный индекс массива.
- high — последний индекс массива.
Алгоритм осуществляет поиск путем вычисления значения индекса:
- Если значение найдено (когда
lys[index] == val), возвращается индекс. - Если значение
valменьшеlys[index], то значение индекса пересчитывается по формуле для левого подмассива. - Если значение
valбольшеlys[index], то значение индекса пересчитывается по формуле для правого подмассива.
Давайте посмотрим на реализацию интерполяционного поиска на Python:
def InterpolationSearch(lys, val):
low = 0
high = (len(lys) - 1)
while low <= high and val >= lys[low] and val <= lys[high]:
index = low + int(((float(high - low) / ( lys[high] - lys[low])) * ( val - lys[low])))
if lys[index] == val:
return index
if lys[index] < val:
low = index + 1;
else:
high = index - 1;
return -1
Если мы используем функцию для вычисления:
>>> print(InterpolationSearch([1,2,3,4,5,6,7,8], 6))
Наши начальные значения будут следующими:
val = 6,
low = 0,
high = 7,
lys[low] = 1,
lys[high] = 8,
index = 0 + [(6-1)*(7-0)/(8-1)] = 5
Поскольку lys[5] равно 6, что является искомым значением, мы прекращаем выполнение и возвращаем результат:
5
Если у нас большое количество элементов и наш индекс не может быть вычислен за одну итерацию, то мы продолжаем пересчитывать значение индекса после корректировки значений high и low.
Временная сложность интерполяционного поиска равна O(log log n), когда значения распределены равномерно. Если значения распределены неравномерно, временная сложность для наихудшего случая равна O(n) — так же, как и для линейного поиска.
Интерполяционный поиск лучше всего работает на равномерно распределенных, отсортированных массивах. В то время как бинарный поиск начинает поиск с середины и всегда делит массив на две части, интерполяционный поиск вычисляет вероятную позицию элемента и проверяет индекс, что повышает вероятность нахождения элемента за меньшее количество итераций.
Python очень удобочитаемый и эффективный по сравнению с такими языками программирования, как Java, Fortran, C, C++ и т. д. Одним из ключевых преимуществ использования Python для реализации алгоритмов поиска является то, что вам не нужно беспокоиться о приведении или явной типизации.
В Python большинство алгоритмов поиска, которые мы обсуждали, будут работать так же хорошо, если мы ищем строку. Имейте в виду, что понадобится внести изменения в код для алгоритмов, которые используют искомый элемент для числовых вычислений, например алгоритм интерполяционного поиска.
Python также подходит, если вы хотите сравнить производительность различных алгоритмов поиска для вашего dataset’а. Создание прототипа на Python проще и быстрее, потому что вы можете сделать больше с меньшим количеством строк кода.
Чтобы сравнить производительность наших реализованных алгоритмов, в Python мы можем использовать библиотеку time:
import time start = time.time() # вызовите здесь функцию end = time.time() print(start-end)
Заключение
Существует множество возможных способов поиска элемента в коллекции. В этой статье мы обсудили несколько алгоритмов поиска и их реализации на Python.
Выбор используемого алгоритма зависит от данных, с которыми вы будете работать. Это ваш входной массив, который мы называли lys во всех наших реализациях.
- Если вы хотите выполнить поиск в несортированном массиве или найти первое вхождение искомой переменной, то лучшим вариантом будет линейный поиск.
- Если вы хотите выполнить поиск в отсортированном массиве, есть много вариантов, из которых самый простой и быстрый — это бинарный поиск.
- Если у вас есть отсортированный массив, в котором вы хотите выполнить поиск без использования оператора деления, вы можете использовать либо jump search, либо поиск Фибоначчи.
- Если вы знаете, что искомый элемент, скорее всего, находится ближе к началу массива, вы можете использовать экспоненциальный поиск.
- Если ваш отсортированный массив равномерно распределен, то самым быстрым и эффективным будет интерполяционный поиск.
Если вы не уверены, какой алгоритм использовать для отсортированного массива, просто протестируйте каждый из них при помощи библиотеки time и выберите тот, который лучше всего работает с вашим dataset’ом.
Python hosting: Host, run, and code Python in the cloud!
Arrays are usually referred to as lists. For convience, lets call them arrays in this article.
Python has a method to search for an element in an array, known as index().
We can find an index using:
x = ['p','y','t','h','o','n']
print(x.index('o'))
Arrays start with the index zero (0) in Python:
Python character array
If you would run x.index(‘p’) you would get zero as output (first index).
Related course:
- Python Crash Course: Master Python Programming
Array duplicates: If the array contains duplicates, the index() method will only return the first element.
Find multiple occurences
If you want multiple to find multiple occurrences of an element, use the lambda function below.
get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]
Find in string arrays
To find an element in a string array use:
x = ["Moon","Earth","Jupiter"]
print(x.index("Earth"))
You could use this code if you want to find multiple occurrences:
x = ["Moon","Earth","Jupiter","Neptune","Earth","Venus"]
get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]
print(get_indexes("Earth",x))
Find in numeric array
The index method works on numeric arrays too:
x = [5,1,7,0,3,4]
print(x.index(7))
To find multiple occurrences you can use this lambda function:
x = [5,1,7,0,3,4,5,3,2,6,7,3,6]
get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]
print(get_indexes(7,x))
In this article you will learn how to find the index of an element contained in a list in the Python programming language.
There are a few ways to achieve this, and in this article you will learn three of the different techniques used to find the index of a list element in Python.
The three techniques used are:
- finding the index using the
index()list method, - using a
for-loop, - and finally, using list comprehension and the
enumerate()function.
Specifically, here is what we will cover in depth:
- An overview of lists in Python
- How indexing works
- Use the
index()method to find the index of an item
1.Use optional parameters with theindex()method - Get the indices of all occurrences of an item in a list
- Use a
for-loopto get indices of all occurrences of an item in a list - Use list comprehension and the
enumerate()function to get indices of all occurrences of an item in a list
- Use a
What are Lists in Python?
Lists are a built-in data type in Python, and one of the most powerful data structures.
They act as containers and store multiple, typically related, items under the same variable name.
Items are placed and enclosed inside square brackets, []. Each item inside the square brackets is separated by a comma, ,.
# a list called 'my_information' that contains strings and numbers
my_information = ["John Doe", 34, "London", 1.76]
From the example above, you can see that lists can contain items that are of any data type, meaning list elements can be heterogeneous.
Unlike arrays that only store items that are of the same type, lists allow for more flexibility.
Lists are also mutable, which means they are changeable and dynamic. List items can be updated, new items can be added to the list, and any item can be removed at any time throughout the life of the program.
An Overview of Indexing in Python
As mentioned, lists are a collection of items. Specifically, they are an ordered collection of items and they preserve that set and defined order for the most part.
Each element inside a list will have a unique position that identifies it.
That position is called the element’s index.
Indices in Python, and in all programming languages, start at 0 and not 1.
Let’s take a look at the list that was used in the previous section:
my_information = ["John Doe", 34, "London", 1.76]
The list is zero-indexed and counting starts at 0.
The first list element, "John Doe", has an index of 0.
The second list element, 34, has an index of 1.
The third list element, "London", has an index of 2.
The forth list element, 1.76, has an index of 3.
Indices come in useful for accessing specific list items whose position (index) you know.
So, you can grab any list element you want by using its index.
To access an item, first include the name of the list and then in square brackets include the integer that corresponds to the index for the item you want to access.
Here is how you would access each item using its index:
my_information = ["John Doe", 34, "London", 1.76]
print(my_information[0])
print(my_information[1])
print(my_information[2])
print(my_information[3])
#output
#John Doe
#34
#London
#1.76
But what about finding the index of a list item in Python?
In the sections that follow you will see some of the ways you can find the index of list elements.
So far you’ve seen how to access a value by referencing its index number.
What happens though when you don’t know the index number and you’re working with a large list?
You can give a value and find its index and in that way check the position it has within the list.
For that, Python’s built-in index() method is used as a search tool.
The syntax of the index() method looks like this:
my_list.index(item, start, end)
Let’s break it down:
my_listis the name of the list you are searching through..index()is the search method which takes three parameters. One parameter is required and the other two are optional.itemis the required parameter. It’s the element whose index you are searching for.startis the first optional parameter. It’s the index where you will start your search from.endthe second optional parameter. It’s the index where you will end your search.
Let’s see an example using only the required parameter:
programming_languages = ["JavaScript","Python","Java","C++"]
print(programming_languages.index("Python"))
#output
#1
In the example above, the index() method only takes one argument which is the element whose index you are looking for.
Keep in mind that the argument you pass is case-sensitive. This means that if you had passed «python», and not «Python», you would have received an error as «python» with a lowercase «p» is not part of the list.
The return value is an integer, which is the index number of the list item that was passed as an argument to the method.
Let’s look at another example:
programming_languages = ["JavaScript","Python","Java","C++"]
print(programming_languages.index("React"))
#output
#line 3, in <module>
# print(programming_languages.index("React"))
#ValueError: 'React' is not in list
If you try and search for an item but there is no match in the list you’re searching through, Python will throw an error as the return value — specifically it will return a ValueError.
This means that the item you’re searching for doesn’t exist in the list.
A way to prevent this from happening, is to wrap the call to the index() method in a try/except block.
If the value does not exist, there will be a message to the console saying it is not stored in the list and therefore doesn’t exist.
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
try:
print(programming_languages.index("React"))
except ValueError:
print("That item does not exist")
#output
#That item does not exist
Another way would be to check to see if the item is inside the list in the first place, before looking for its index number. The output will be a Boolean value — it will be either True or False.
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
print("React" in programming_languages)
#output
#False
How to Use the Optional Parameters with the index() Method
Let’s take a look at the following example:
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
print(programming_languages.index("Python"))
#output
#1
In the list programming_languages there are three instances of the «Python» string that is being searched.
As a way to test, you could work backwards as in this case the list is small.
You could count and figure out their index numbers and then reference them like you’ve seen in previous sections:
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
print(programming_languages[1])
print(programming_languages[3])
print(programming_languages[5])
#output
#Python
#Python
#Python
There is one at position 1, another one at position 3 and the last one is at position 5.
Why aren’t they showing in the output when the index() method is used?
When the index() method is used, the return value is only the first occurence of the item in the list. The rest of the occurrences are not returned.
The index() method returns only the index of the position where the item appears the first time.
You could try passing the optional start and end parameters to the index() method.
You already know that the first occurence starts at index 1, so that could be the value of the start parameter.
For the end parameter you could first find the length of the list.
To find the length, use the len() function:
print(len(programming_languages))
#output is 6
The value for end parameter would then be the length of the list minus 1. The index of the last item in a list is always one less than the length of the list.
So, putting all that together, here is how you could try to get all three instances of the item:
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
print(programming_languages.index("Python",1,5))
#output
#1
The output still returns only the first instance!
Although the start and end parameters provide a range of positions for your search, the return value when using the index() method is still only the first occurence of the item in the list.
How to Get the Indices of All Occurrences of an Item in A List
Use a for-loop to Get the Indices of All Occurrences of an Item in A List
Let’s take the same example that we’ve used so far.
That list has three occurrences of the string «Python».
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
First, create a new, empty list.
This will be the list where all indices of «Python» will be stored.
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
python_indices = []
Next, use a for-loop. This is a way to iterate (or loop) through the list, and get each item in the original list. Specifically, we loop over each item’s index number.
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
python_indices = []
for programming_language in range(len(programming_languages)):
You first use the for keyword.
Then create a variable, in this case programming_language, which will act as a placeholder for the position of each item in the original list, during the iterating process.
Next, you need to specify the set amount of iterations the for-loop should perform.
In this case, the loop will iterate through the full length of the list, from start to finish. The syntax range(len(programming_languages)) is a way to access all items in the list programming_languages.
The range() function takes a sequence of numbers that specify the number it should start counting from and the number it should end the counting with.
The len() function calculates the length of the list, so in this case counting would start at 0 and end at — but not include — 6, which is the end of the list.
Lastly, you need to set a logical condition.
Essentially, you want to say: «If during the iteration, the value at the given position is equal to ‘Python’, add that position to the new list I created earlier».
You use the append() method for adding an element to a list.
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
python_indices = []
for programming_language in range(len(programming_languages)):
if programming_languages[programming_language] == "Python":
python_indices.append(programming_language)
print(python_indices)
#output
#[1, 3, 5]
Use List Comprehension and the enumerate() Function to Get the Indices of All Occurrences of an Item in A List
Another way to find the indices of all the occurrences of a particular item is to use list comprehension.
List comprehension is a way to create a new list based on an existing list.
Here is how you would get all indices of each occurrence of the string «Python», using list comprehension:
programming_languages = ["JavaScript","Python","Java","Python","C++","Python"]
python_indices = [index for (index, item) in enumerate(programming_languages) if item == "Python"]
print(python_indices)
#[1, 3, 5]
With the enumerate() function you can store the indices of the items that meet the condition you set.
It first provides a pair (index, item) for each element in the list (programming_languages) that is passed as the argument to the function.
index is for the index number of the list item and item is for the list item itself.
Then, it acts as a counter which starts counting from 0 and increments each time the condition you set is met, selecting and moving the indices of the items that meet your criteria.
Paired with the list comprehension, a new list is created with all indices of the string «Python».
Conclusion
And there you have it! You now know some of the ways to find the index of an item, and ways to find the indices of multiple occurrences of an item, in a list in Python.
I hope you found this article useful.
To learn more about the Python programming language, check out freeCodeCamp’s Scientific Computing with Python Certification.
You’ll start from the basics and learn in an interacitve and beginner-friendly way. You’ll also build five projects at the end to put into practice and help reinforce what you’ve learned.
Thanks for reading and happy coding!
Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started


