Since it has not been mentioned just for completion.
The good ol’ filter to filter your to be filtered elements.
Functional programming ftw.
####### Set Up #######
class X:
def __init__(self, val):
self.val = val
elem = 5
my_unfiltered_list = [X(1), X(2), X(3), X(4), X(5), X(5), X(6)]
####### Set Up #######
### Filter one liner ### filter(lambda x: condition(x), some_list)
my_filter_iter = filter(lambda x: x.val == elem, my_unfiltered_list)
### Returns a flippin' iterator at least in Python 3.5 and that's what I'm on
print(next(my_filter_iter).val)
print(next(my_filter_iter).val)
print(next(my_filter_iter).val)
### [1, 2, 3, 4, 5, 5, 6] Will Return: ###
# 5
# 5
# Traceback (most recent call last):
# File "C:UsersmousavinworkspaceScriptstest.py", line 22, in <module>
# print(next(my_filter_iter).value)
# StopIteration
# You can do that None stuff or whatever at this point, if you don't like exceptions.
I know that generally in python list comprehensions are preferred or at least
that is what I read, but I don’t see the issue to be honest. Of course Python is not an FP language, but Map / Reduce / Filter are perfectly readable and are the most standard of standard use cases in functional programming.
So there you go. Know thy functional programming.
filter condition list
It won’t get any easier than this:
next(filter(lambda x: x.val == value, my_unfiltered_list)) # Optionally: next(..., None) or some other default value to prevent Exceptions
На чтение 4 мин Просмотров 5.6к. Опубликовано 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. Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂
What is a good way to find the index of an element in a list in Python?
Note that the list may not be sorted.
Is there a way to specify what comparison operator to use?
asked Mar 3, 2009 at 1:45
2
From Dive Into Python:
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.index("example")
5
stivlo
83.2k31 gold badges142 silver badges199 bronze badges
answered Mar 3, 2009 at 1:52
3
If you just want to find out if an element is contained in the list or not:
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> 'example' in li
True
>>> 'damn' in li
False
answered Feb 17, 2011 at 10:00
EduardoEduardo
1,7811 gold badge11 silver badges5 bronze badges
0
The best way is probably to use the list method .index.
For the objects in the list, you can do something like:
def __eq__(self, other):
return self.Value == other.Value
with any special processing you need.
You can also use a for/in statement with enumerate(arr)
Example of finding the index of an item that has value > 100.
for index, item in enumerate(arr):
if item > 100:
return index, item
Source
tedder42
23.2k12 gold badges86 silver badges100 bronze badges
answered Mar 3, 2009 at 1:51
Brian R. BondyBrian R. Bondy
338k124 gold badges592 silver badges635 bronze badges
Here is another way using list comprehension (some people might find it debatable). It is very approachable for simple tests, e.g. comparisons on object attributes (which I need a lot):
el = [x for x in mylist if x.attr == "foo"][0]
Of course this assumes the existence (and, actually, uniqueness) of a suitable element in the list.
answered Sep 24, 2010 at 9:35
ThomasHThomasH
22.1k13 gold badges60 silver badges61 bronze badges
3
assuming you want to find a value in a numpy array,
I guess something like this might work:
Numpy.where(arr=="value")[0]
Jorgesys
124k23 gold badges329 silver badges265 bronze badges
answered Jan 27, 2011 at 15:03
2
There is the index
method, i = array.index(value)
, but I don’t think you can specify a custom comparison operator. It wouldn’t be hard to write your own function to do so, though:
def custom_index(array, compare_function):
for i, v in enumerate(array):
if compare_function(v):
return i
answered Mar 3, 2009 at 1:50
David ZDavid Z
127k27 gold badges253 silver badges278 bronze badges
I use function for returning index for the matching element (Python 2.6):
def index(l, f):
return next((i for i in xrange(len(l)) if f(l[i])), None)
Then use it via lambda function for retrieving needed element by any required equation e.g. by using element name.
element = mylist[index(mylist, lambda item: item["name"] == "my name")]
If i need to use it in several places in my code i just define specific find function e.g. for finding element by name:
def find_name(l, name):
return l[index(l, lambda item: item["name"] == name)]
And then it is quite easy and readable:
element = find_name(mylist,"my name")
answered Oct 20, 2011 at 12:30
jkijki
4,6171 gold badge34 silver badges29 bronze badges
0
The index method of a list will do this for you. If you want to guarantee order, sort the list first using sorted()
. Sorted accepts a cmp or key parameter to dictate how the sorting will happen:
a = [5, 4, 3]
print sorted(a).index(5)
Or:
a = ['one', 'aardvark', 'a']
print sorted(a, key=len).index('a')
answered Mar 3, 2009 at 1:52
Jarret HardieJarret Hardie
94.4k10 gold badges132 silver badges126 bronze badges
how’s this one?
def global_index(lst, test):
return ( pair[0] for pair in zip(range(len(lst)), lst) if test(pair[1]) )
Usage:
>>> global_index([1, 2, 3, 4, 5, 6], lambda x: x>3)
<generator object <genexpr> at ...>
>>> list(_)
[3, 4, 5]
answered Mar 3, 2009 at 2:06
2
I found this by adapting some tutos. Thanks to google, and to all of you
def findall(L, test):
i=0
indices = []
while(True):
try:
# next value in list passing the test
nextvalue = filter(test, L[i:])[0]
# add index of this value in the index list,
# by searching the value in L[i:]
indices.append(L.index(nextvalue, i))
# iterate i, that is the next index from where to search
i=indices[-1]+1
#when there is no further "good value", filter returns [],
# hence there is an out of range exeption
except IndexError:
return indices
A very simple use:
a = [0,0,2,1]
ind = findall(a, lambda x:x>0))
[2, 3]
P.S. scuse my english
answered Oct 16, 2011 at 11:41
Получение индекса для строк: str.index (), str.rindex() и str.find(), str.rfind()
String
также имеет index
метод , но и более продвинутые варианты и дополнительное str.find
.Для обоих из них есть дополнительный обратный метод.
astring = 'Hello on StackOverflow'
astring.index('o') # 4
astring.rindex('o') # 20
astring.find('o') # 4
astring.rfind('o') # 20
Разница между index
/ rindex
и find
/ rfind
это то , что происходит , если подстрока не найдена в строке:
astring.index('q') # ValueError: substring not found
astring.find('q') # -1
Все эти методы позволяют начальный и конечный индексы:
astring.index('o', 5) # 6
astring.index('o', 6) # 6 - start is inclusive
astring.index('o', 5, 7) # 6
astring.index('o', 5, 6) # - end is not inclusive
ValueError: подстрока не найдена
astring.rindex('o', 20) # 20
astring.rindex('o', 19) # 20 - still from left to right
astring.rindex('o', 4, 7) # 6
В поисках элемента
Все встроенные в коллекции в Python реализовать способ проверить членство элемента с использованием in
. Список
alist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
5 in alist # True
10 in alist # False
Кортеж
atuple =('0', '1', '2', '3', '4')
4 in atuple # False
'4' in atuple # True
строка
astring = 'i am a string'
'a' in astring # True
'am' in astring # True
'I' in astring # False
Задавать
aset = {(10, 10), (20, 20), (30, 30)}
(10, 10) in aset # True
10 in aset # False
Dict
dict
немного особенный: нормальный in
проверяет только ключи. Если вы хотите , чтобы искать в значении , которые необходимо указать. То же самое , если вы хотите найти пар ключ-значение.
adict = {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
1 in adict # True - implicitly searches in keys
'a' in adict # False
2 in adict.keys() # True - explicitly searches in keys
'a' in adict.values() # True - explicitly searches in values
(0, 'a') in adict.items() # True - explicitly searches key/value pairs
Получение списка индексов и кортежей: list.index(), tuple.index()
list
и tuple
имеют index
-метода получить позицию элемента:
alist = [10, 16, 26, 5, 2, 19, 105, 26]
# search for 16 in the list
alist.index(16) # 1
alist[1] # 16
alist.index(15)
Ошибка значения: 15 отсутствует в списке
Но возвращает только позицию первого найденного элемента:
atuple = (10, 16, 26, 5, 2, 19, 105, 26)
atuple.index(26) # 2
atuple[2] # 26
atuple[7] # 26 - is also 26!
Поиск ключа(ей) по значению в dict
dict
не имеет встроенный метода для поиска значения или ключа , потому что словари являются упорядоченными. Вы можете создать функцию, которая получает ключ (или ключи) для указанного значения:
def getKeysForValue(dictionary, value):
foundkeys = []
for keys in dictionary:
if dictionary[key] == value:
foundkeys.append(key)
return foundkeys
Это также может быть записано как эквивалентное понимание списка:
def getKeysForValueComp(dictionary, value):
return [key for key in dictionary if dictionary[key] == value]
Если вам нужен только один найденный ключ:
def getOneKeyForValue(dictionary, value):
return next(key for key in dictionary if dictionary[key] == value)
Первые две функции возвращает list
всех keys
, которые имеют определенное значение:
adict = {'a': 10, 'b': 20, 'c': 10}
getKeysForValue(adict, 10) # ['c', 'a'] - order is random could as well be ['a', 'c']
getKeysForValueComp(adict, 10) # ['c', 'a'] - dito
getKeysForValueComp(adict, 20) # ['b']
getKeysForValueComp(adict, 25) # []
Другой вернет только один ключ:
getOneKeyForValue(adict, 10) # 'c' - depending on the circumstances this could also be 'a'
getOneKeyForValue(adict, 20) # 'b'
и поднять StopIteration
— Exception
, если значение не в dict
:
getOneKeyForValue(adict, 25)
StopIteration
Получение индекса для отсортированных последовательностей: bisect.bisect_left()
Отсортированные последовательности позволяют использовать более быстрый поиск алгоритмов: bisect.bisect_left()
[1]:
import bisect
def index_sorted(sorted_seq, value):
"""Locate the leftmost value exactly equal to x or raise a ValueError"""
i = bisect.bisect_left(sorted_seq, value)
if i != len(sorted_seq) and sorted_seq[i] == value:
return i
raise ValueError
alist = [i for i in range(1, 100000, 3)] # Sorted list from 1 to 100000 with step 3
index_sorted(alist, 97285) # 32428
index_sorted(alist, 4) # 1
index_sorted(alist, 97286)
ValueError
Для очень больших отсортированных последовательностей выигрыш в скорости может быть достаточно высоким. В случае первого поиска примерно в 500 раз быстрее:
%timeit index_sorted(alist, 97285)
# 100000 loops, best of 3: 3 µs per loop
%timeit alist.index(97285)
# 1000 loops, best of 3: 1.58 ms per loop
Хотя это немного медленнее, если элемент является одним из самых первых:
%timeit index_sorted(alist, 4)
# 100000 loops, best of 3: 2.98 µs per loop
%timeit alist.index(4)
# 1000000 loops, best of 3: 580 ns per loop
Поиск вложенных последовательностей
Поиск во вложенных последовательностях , как в list
из tuple
требует такого подхода , как поиск ключей для значений в dict
, но нуждается в пользовательских функциях.
Индекс самой внешней последовательности, если значение было найдено в последовательности:
def outer_index(nested_sequence, value):
return next(index for index, inner in enumerate(nested_sequence)
for item in inner
if item == value)
alist_of_tuples = [(4, 5, 6), (3, 1, 'a'), (7, 0, 4.3)]
outer_index(alist_of_tuples, 'a') # 1
outer_index(alist_of_tuples, 4.3) # 2
или индекс внешней и внутренней последовательности:
def outer_inner_index(nested_sequence, value):
return next((oindex, iindex) for oindex, inner in enumerate(nested_sequence)
for iindex, item in enumerate(inner)
if item == value)
outer_inner_index(alist_of_tuples, 'a') # (1, 2)
alist_of_tuples[1][2] # 'a'
outer_inner_index(alist_of_tuples, 7) # (2, 0)
alist_of_tuples[2][0] # 7
В общем случае (не всегда) с помощью next
и выражения генератора с условиями , чтобы найти первое вхождение искомого значения является наиболее эффективным подходом.
Поиск в пользовательских классах: __contains__ и __iter__
Для того, чтобы разрешить использование in
пользовательских классах класса должен либо предоставить магический метод __contains__
или, если это невозможно, в __iter__
-метод.
Предположим , у вас есть класс , содержащий list
из list
s:
class ListList:
def __init__(self, value):
self.value = value
# Create a set of all values for fast access
self.setofvalues = set(item for sublist in self.value for item in sublist)
def __iter__(self):
print('Using __iter__.')
# A generator over all sublist elements
return (item for sublist in self.value for item in sublist)
def __contains__(self, value):
print('Using __contains__.')
# Just lookup if the value is in the set
return value in self.setofvalues
# Even without the set you could use the iter method for the contains-check:
# return any(item == value for item in iter(self))
Использование тестирования членства возможно при использовании in
:
a = ListList([[1,1,1],[0,1,1],[1,5,1]])
10 in a # False
# Prints: Using __contains__.
5 in a # True
# Prints: Using __contains__.
даже после удаления __contains__
метода:
del ListList.__contains__
5 in a # True
# Prints: Using __iter__.
Примечание: зацикливание in
(как for i in a
) всегда будет использовать __iter__
даже если класс реализует __contains__
метод.
Lists are among the most commonly used data types in Python. They can store any kind of object, are easily extendable, and many programs use them to process collections of items.
At times, however, you may not need to access an entire list, but instead a specific element. Maybe you want to know if an item occurs in a list, or whether one list contains the same elements as another. How would you proceed? In this article, we’ll cover the most effective ways to find an item in a Python list.
What Is a Python List?
A list in Python is a collection of elements. The elements in a list can be of any data type:
>>> cool_stuff = [17.5, 'penguin', True, {'one': 1, 'two': 2}, []]
This list contains a floating point number, a string, a Boolean value, a dictionary, and another, empty list. In fact, a Python list can hold virtually any type of data structure.
A student of Python will also learn that lists are ordered, meaning that the order of their elements is fixed. Unless you alter the list in any way, a given item’s position will always be the same. This is different from sets and dictionaries, which are unordered.
Sets and dictionaries cannot contain the same element twice. For lists, that’s no problem. In fact, here is an entirely conceivable list in Python:
>>> penguins = ['penguin'] * 5 >>> penguins ['penguin', 'penguin', 'penguin', 'penguin', 'penguin']
Finally, Python lists are “mutable,” meaning they can be changed. This sets them apart from tuples, which are immutable. One of the most common list operations is appending items to the end of a list:
>>> cool_birds = ['robin', 'penguin', 'kiwi', 'kingfisher'] >>> cool_birds.append('kakapo') >>> cool_animals ['robin', 'penguin', 'kiwi', 'kingfisher', 'kakapo']
Our list of cool birds has gained a new member!
Checking Whether a List Contains an Item
Why might you want to find items in a list in the first place? One use case may be simply checking if an item is part of a list or not. In this section, we’ll be looking at two different methods to do that.
The in
Operator
If you don’t need to know the number of occurrences, you could simply use the in
operator, which will return the Boolean value True, if the list contains the item:
>>> 'robin' in cool_birds True
And it’ll return “False” if not:
>>> 'kookaburra' in cool_birds False
The in
Operator and Sets
The in
operator is simple and easy to remember. But in combination with lists, it is not particularly fast. That’s because when we want to check for an item, our program first has to process the entire list. If our list does not contain the item, Python will still have to loop through all the elements in the list before it can put out “False.”
In practice, time complexity is usually only an issue with very long lists. If you’re working with a longer list, it’s a good idea to convert a list to a set before using in
. That’s because sets (like Python dictionaries) use a lookup, or hash table to check whether an item exists. Hash tables considerably speed up the lookup process:
>>> import timeit >>> long_list_of_numbers = range(1000000) >>> large_set_of_numbers = set(long_list_of_numbers) >>> timeit.timeit('999999 in long_list_of_numbers', globals=globals()) 0.11862506601028144
Using range(), we created a long list containing all numbers from 0 to 999,999. It took about 120 milliseconds to check whether the list contained 999,999, which is its last number.
>>> timeit.timeit('999999 in large_set_of_numbers', globals=globals()) 0.0623531190212816
This same operation was almost twice as fast on a set. But it’s longer to create a set than a list, so the time gain really only pays off if you’re performing multiple lookups.
Sets also provide a handy way of checking whether two lists contain the same elements—regardless of their individual order, or how many times an item occurs in a list. By converting the lists to sets, you can compare them with the equality operator (==):
>>> list1 = ['kiwi', 'kiwi', 'kiwi', 'kiwi', 'kakapo'] >>> list2 = ['kakapo', 'kiwi'] >>> list1 == list2 False >>> set(list1) == set(list2) True
While the two lists are certainly not identical, they do contain the same items, which we discovered by using sets.
The count()
Method
Sometimes you’ll need to go beyond knowing whether a list contains an item. You might also want to determine the number of that item’s occurrences. If that’s the case, you can use count:
>>> penguins.count('penguin') 5
Just like the in
operator, you can use count()
even if the item is not in the list:
>>> penguins.count('kookaburra') 0
Finding Items and Their Positions
Other times, it’s not enough to check whether an item is part of a list, or even how many times. In this section, we’ll be looking at how to get the indices of one or more items in a list.
The index()
Method
Since lists are ordered, there is value in knowing an item’s exact position within a list. Maybe you want to use the index for slicing, or splitting a list into several smaller lists. The simplest way to do so would be to use index()
:
>>> cool_birds.index('kiwi') 2 # Remember that Python starts counting at 0
Note that index()
only ever returns the position of the first item. When an item is not actually in a list, index()
throws an error that stops the program:
>>> cool_birds.index('kookaburra') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: 'kookaburra' is not in list
The enumerate()
Function
If you want to get the indices of all
occurrences of an item, you can use enumerate()
. This is a very handy function that “zips” together a number range and a list. Coupled with an if-condition, enumerate()
helps us find our indices. Consider the following example, where we use a second list to store the indices:
>>> indices = []>>> for i, bird in enumerate(cool_birds): ... if bird == 'penguin': ... indices.append(i) ... >>> indices [1]
We might even use a broader matching condition. For example, we could change the if-condition so that it matches every cool bird starting with a “k”:
>>> for i, bird in enumerate(cool_birds): ... if bird[0] == 'k': ... indices.append(i) ... >>> indices [2, 3, 4]
Unfortunately, this method takes up a lot of space—three lines, as compared to our index() function, which only uses one line! If you have some Python experience, you may have already guessed our solution to this dilemma: the list comprehension.
List Comprehensions
A list comprehension lets you write an entire for-loop—including the if-condition—on the same line, and returns a list of the results:
>>> indices = [i for i, bird in enumerate(cool_birds) if bird[0] == 'k'] >>> indices [2, 3, 4]
How about extracting all numbers divisible by 123456?
>>> indices = [i for i, x in enumerate(long_list_of_numbers) if x % 123456 == 0] >>> indices [0, 123456, 246912, 370368, 493824, 617280, 740736, 864192, 987648]
List comprehension syntax is great if you want to save some space in your code. Many developers also find it more readable than the nested for-loop.
Using NumPy for Numerical Data
You’re now aware of the pros and cons of lists and sets when it comes to allocating items in a Python data collection. But if you’re working with numerical data, there’s another data type that you should know about: NumPy arrays. To understand what sets arrays apart from lists, let’s take a closer look at how Python implements the latter.
Python lists are really linked lists. Each item is assigned a separate, quasi-random place in memory, and it contains a pointer to the address of the next item. This is why operations pertaining to list-traversal are so expensive. To look at every item in the list, your program has to jump from one element to the next.
Arrays on the other hand are stored in contiguous memory. That’s why, when you create a Numpy array, you need to tell it the kind of data type you want to store, so that it can reserve enough space in memory for your array to fit.
To look up items in a numpy array, use where()
:
>>> import numpy as np >>> long_array_of_numbers = np.arange(1000000) >>> indices = np.where(long_array_of_numbers % 123456 == 0)>>> indices (array([0, 123456, 246912, 370368, 493824, 617280, 740736, 864192, 987648]),)
This method is as time-efficient as our list comprehension—and it’s syntax is even more readable. NumPy is undoubtedly one of the most important Python libraries out there. Whether you’re planning to get into machine learning, data science, or geospatial modeling: NumPy will be your best friend.
Continue Your Python Journey
In this tutorial, we looked into methods for finding items in a Python list. From the in operator to list comprehensions, we used strategies of varying complexity. Along the way, we discussed the pros and cons of working with different data structures such as lists, sets, and NumPy arrays.
Looking to take your Python skills to the next level?
Enroll in our Introduction to Programming nanodegree, where you’ll master fundamental Python concepts like logic checks, data structures, and functions.