Python find first element in list by condition

Найти первый элемент списка по условию

Пускай имеется такая задача: дан список с численными элементами. Требуется найти и вернуть первый отрицательный элемент. Казалось бы, должна быть какая-нибудь встроенная функция для этого, но нет. Придется писать ее самим. Решение в лоб:

items = [1, 3, 5, -17, 20, 3, -6] for x in items: if x < 0: print(x) break else: print('not found')

Такое решение работает, но выглядит скорее по-бейсиковски, нежели чем по-питоновски. Пытаясь проявить смекалку, некоторые извращаются и пишут так:

result = list(filter(lambda x: x < 0, items))[0] print(result)

По-моему, стало гораздо сложнее, хоть и в одну строку. А может лучше так:

result = [x for x in items if x < 0][0]

Что ж, теперь лаконичнее, но все равно не идеал. Какая самая большая ошибка здесь? Что в первом, что во втором случае идет перебор всего итератора до конца, а потом отбрасываются все лишние значения, кроме нулевого индекса. Тогда как изначальный код останавливается, найдя нужно значение, экономя и время, и память.

Правильное решение

Лучше использовать встроенную функцию next – она возвращает следующий элемент из итератора, а в качестве итератора мы напишем генераторное выражение с if. Вот так:

result = next(x for x in items if x < 0)

Вот это коротко, экономно и очень по-питоновски (in a pythonic way). Остается одна проблемка: если элемент не найден, что будет брошено исключение StopIteration. Чтобы подавить его, достаточно вторым аргументом в next передать значение по-умолчанию. Если оно задано, то оно будет возвращено вместо возбуждения исключения, если в итераторе нет элементов, то есть не найдено удовлетворяющих условию элементов в исходной коллекции. И не забыть обернуть генераторное выражение в скобки:

items = [1, 2, 4] result = next((x for x in items if x < 0), 'not found') print(result) # not found

С произвольной функцией, задающей критерий поиска (ее еще называют предикат – predicate) это выглядит так:

def is_odd(x): return x % 2 != 0 result = next(x for x in items if is_odd(x)) # или еще лучше result = next(filter(is_odd, items))

Так как в Python 3 filter работает лениво, как и генератор, она не «обналичивает» весь исходный список через фильтр, а лишь идет до первого удачно-выполненного условия. Любите итераторы! ✌️

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈

Источник

Find the first element in Python list that matches some condition

Python

Sometimes you'll have a list in python and you'd like to find the first element in that list that matches some arbitrary condition. We'll see now how to do that.

For our example the condition is very simple, the length of a string being longer than 5 characters.

Читайте также:  Bukkit check java version

Oh and if you are interested, I also wrote a solution to find the first matching element using Perl where there is a function called first.

Find first element using a for loop

The first solution that might come to mind is using a for loop. Grammatically I find it strange, but Python has a nice programming technique. You can add an else part to a for-loop and this else part will be executed if the loop finished "normally", without calling break.

examples/python/first_loop.py

animals = ['snake', 'camel', 'etruscan shrew', 'ant', 'hippopotamus', 'giraffe'] for animal in animals: if len(animal) > 5: first = animal break else: first = None print(first) # etruscan shrew

Find first element using filter and next

Another way that is more compact and some people might find nicer is to use the filter function of Python. Usually we use it to create a shorter list of elements meeting some condition. In this case however we don't need to store the result of the filter call in a variable. Instead we can call the next function. This will return the next element returned by the filter object. Which, in our case, will be the first element in the list.

The only issue is that if there were no matching values, this call would raise an exception. Adding a second parameter to the next() call, Python will return that value. None, in our case.

I've added a second copy to the solution in which I've separated the steps: First assigning the result of filter to a variable and then calling next on it. It is there only to make it easier to understand the construct.

examples/python/first_filter.py

animals = ['snake', 'camel', 'etruscan shrew', 'ant', 'hippopotamus', 'giraffe'] first = next(filter(lambda animal: len(animal) > 5, animals), None) print(first) print('-------') filtered_list = filter(lambda animal: len(animal) > 5, animals) print(filtered_list) first = next(filtered_list, None) print(first)

The output will look like this:

etruscan shrew ------- etruscan shrew

Show the operations

In Python 2 filter would have returned a list already checking all the values of the original list. That would be a waste of time and CPU. The filter function in Python 3 returns a filter object and only executes the filtering condition when the user actually wants to find the next element in the filtered list. You believe me (and the documentation)? Do you want to see it with your own eyes? Fair enough, let's try it.

In this example, instead of a lambda-function I used a function defined using def and in this function I've added a print-statement as well so we can see when it is executed and with what values?

examples/python/first_filter_log.py

animals = ['snake', 'camel', 'etruscan shrew', 'ant', 'hippopotamus', 'giraffe'] def condition(animal): print(f"len()") return len(animal) > 5 first = next(filter(condition, animals), None) print(first)
len(snake) len(camel) len(etruscan shrew) etruscan shrew

As you can see it stopped calling the condition function once it encountered the first matching string.

Etruscan shrew

In case you were wondering the Etruscan shrew is the smallest mammal by mass.

Etruscan shrew

There is a shorter mammal, but this looks better.

Gabor Szabo

If you have any comments or questions, feel free to post them on the source of this page in GitHub. Source on GitHub. Comment on this post

Читайте также:  Python dictionary get all keys with value

Author: Gabor Szabo

Gábor who writes the articles of the Code Maven site offers courses in in the subjects that are discussed on this web site.

Gábor helps companies set up test automation, CI/CD Continuous Integration and Continuous Delivery and other DevOps related systems. Gabor can help your team improve the development speed and reduce the risk of bugs.

He is also the author of a number of eBooks.

Contact Gabor if you'd like to hire his services.

If you would like to support his freely available work, you can do it via Patreon, GitHub, or PayPal.

Источник

Python find first element in list by condition

Last updated: Feb 22, 2023
Reading time · 4 min

banner

# Table of Contents

# Get the first item in a list that matches condition - Python

To get the first item in a list that matches a condition:

  1. Use a generator expression to iterate over the list.
  2. Check if each item in the list meets the condition.
  3. Use the next() function to get the first item that meets the condition.
Copied!
my_list = [1, 3, 7, 14, 29, 35, 105] first_match = next( (item for item in my_list if item > 14), None ) print(first_match) # 👉️ 29

get first item in list that matches condition

The same approach can be used to get the first item in any iterable that matches a condition. The iterable doesn't have to be a list object.

We used a generator expression to iterate over the list.

Generator expressions are used to perform some operation for every element or select a subset of elements that meet a condition.

On each iteration, we check if the current list item is greater than 14 and return the result.

The next() function returns the next item from the provided iterator.

The function can be passed a default value as the second argument.

If the iterator is exhausted or empty, the default value is returned.

If the iterator is exhausted or empty and no default value is provided, a StopIteration exception is raised.

We specified a default value of None but you can use any other value.

Copied!
my_list = [1, 3, 7, 14] first_match = next( (item for item in my_list if item > 14), None ) print(first_match) # 👉️ None

None of the items in the list meet the condition, so the default value is returned.

You can use this approach to get the first item in a list that matches any condition.

Copied!
my_list = ['bobby', 'hadz', 'com'] first_match = next( (item for item in my_list if 'bo' in item), None ) print(first_match) # 👉️ bobby

We used the in operator to get the first list item that contains a specific substring.

The in operator tests for membership. For example, x in l evaluates to True if x is a member of l , otherwise it evaluates to False .

Alternatively, you can use a simple for loop.

# Get the first item in a list that matches condition using a for loop

This is a four-step process:

  1. Use a for loop to iterate over the list.
  2. Check if each item meets the condition.
  3. Once the condition is met, assign the value to a variable.
  4. Use the break statement to break out of the for loop.
Copied!
my_list = [1, 3, 7, 14, 29, 35, 105] first_match = None for item in my_list: if item > 29: first_match = item break print(first_match) # 👉️ 35

get first item in list that matches condition using for loop

We used a for loop to iterate over the list.

Читайте также:  Css file in joomla

On each iteration, we check if the current list item is greater than 29 .

If the condition is met, we assign the value of the item to the first_match variable and exit the loop.

The break statement breaks out of the innermost enclosing for or while loop.

There is no need to continue iterating once we've found the first item that meets the condition.

If you need to find all the list items that meet the condition, append the matching elements to a list and remove the break statement.

Copied!
my_list = [1, 3, 7, 14, 29, 35, 105] matches = [] for item in my_list: if item > 29: matches.append(item) print(matches) # 👉️ [35, 105]

The list.append() method adds an item to the end of the list.

Copied!
my_list = ['bobby', 'hadz'] my_list.append('com') print(my_list) # 👉️ ['bobby', 'hadz', 'com']

The method returns None as it mutates the original list.

Alternatively, you can use the newer assignment expression syntax.

# Get the first item in a list that matches condition using assignment expression

This is a two-step process:

  1. Use the any() function to find the first item that matches a condition.
  2. Use the assignment expression syntax to assign the first match to a variable.
Copied!
my_list = [1, 3, 7, 14, 29, 35, 105] if any((match := item) > 29 for item in my_list): # 👇️ this runs print(match) # 👉️ 35 else: print('None of the items in the list meets the condition')

get first item in list that matches condition using assignment expression

The := syntax is called assignment expressions in Python.

Assignment expressions allow us to assign to variables within an expression using the NAME := expression syntax.

The any function takes an iterable as an argument and returns True if any element in the iterable is truthy.

On each iteration, we check if the current item is greater than 29 .

If the condition is met, the value of the item gets assigned to the match variable and the if block runs.

If the condition is never met, the else block runs.

# Get the first item in a list that matches condition using filter()

You can also use the filter() function to get the first item in a list that matches a condition.

Copied!
my_list = [1, 3, 7, 14, 29, 35, 105] first_match = next(filter(lambda x: x > 14, my_list), None) print(first_match) # 👉️ 29

get first item in list that matches condition using filter

The filter function takes a function and an iterable as arguments and constructs an iterator from the elements of the iterable for which the function returns a truthy value.

The lambda function we passed to filter gets called with each element in the list.

The function checks if each element is greater than the number 14 and returns the result.

The next() function returns the first matching element or None if no element matches the condition.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.

Источник

Оцените статью