Coder Perfect

Find an item in the list with an attribute equal to a certain value (that meets any condition)


I have a list of items. I’m looking for one (first or whatever) item in this list that has value as an attribute (or method result – whatever).

What is the most effective method of locating it?

Here’s test case:

  class Test:
      def __init__(self, value):
          self.value = value

  import random

  value = 5

  test_list = [Test(random.randint(0,100)) for x in range(1000)]

  # that I would do in Pascal, I don't believe it's anywhere near 'Pythonic'
  for x in test_list:
      if x.value == value:
          print "i found it!"

I don’t believe that utilizing generators and reduce() will make a difference because we’ll still be iterating through a list.

ps. : This is only an example of an equation to value. Of course, we want an element that can be used in every situation.

Asked by seler

Solution #1

next((x for x in test_list if x.value == value), None)

This retrieves the first item from the list that matches the condition, or None if none do. It’s the single-expression form I favor.


for x in test_list:
    if x.value == value:
        print("i found it!")

The naive loop-break version, is perfectly Pythonic — it’s concise, clear, and efficient. To make it match the behavior of the one-liner:

for x in test_list:
    if x.value == value:
        print("i found it!")
    x = None

If you don’t break out of the loop, None will be assigned to x.

Answered by agf

Solution #2

It was just included for the sake of completeness because it had not been discussed previously. The good ol’ filter to filter your elements to be filtered.

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


### [1, 2, 3, 4, 5, 5, 6] Will Return: ###
# 5
# 5
# Traceback (most recent call last):
#   File "C:\Users\mousavin\workspace\Scripts\", 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’m aware that list comprehensions are favoured in Python, or at least that’s what I’ve read, but to be honest, I don’t see the problem. Of course, Python is not a functional programming language, but Map, Reduce, and Filter are the most common use cases in functional programming.

So there you have it. Know what you’re doing when it comes to functional programming.

filter condition list

It doesn’t get much simpler than this:

next(filter(lambda x: x.val == value,  my_unfiltered_list)) # Optionally: next(..., None) or some other default value to prevent Exceptions

Answered by Nima Mousavi

Solution #3

Consider the following scenario: The following is the array we have.

li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]

We now need to locate the object in the array with the id e.

next(x for x in li if x["id"] == 1 )
[x for x in li if x["id"] == 1 ][0]
def find(arr , id):
    for x in arr:
        if x["id"] == id:
            return x
find(li , 1)

‘id’: 1, ‘name’: ‘ronaldo’ is the output of all the previous procedures.

Answered by Mohammad Nazari

Solution #4

This is an old question, but I use it pretty often (for version 3.8). It’s a little syntactic salt, but it beats the top answer in that you can get a list of results (if there are any) by eliminating the [0], and it still defaults to None if nothing is found. Simply change the x.value==value to whatever you’re looking for in any other condition.

_[0] if (_:=[x for x in test_list if x.value==value]) else None

Answered by Colin Hicks

Solution #5

You may also utilize the __eq__ function in your Test class to provide rich comparison and use the in operator. I’m not sure if this is the best method on its own, but it might be beneficial if you need to compare Test instances based on value somewhere else.

class Test:
    def __init__(self, value):
        self.value = value

    def __eq__(self, other):
        """To implement 'in' operator"""
        # Comparing with int (assuming "value" is int)
        if isinstance(other, int):
            return self.value == other
        # Comparing with another Test object
        elif isinstance(other, Test):
            return self.value == other.value

import random

value = 5

test_list = [Test(random.randint(0,100)) for x in range(1000)]

if value in test_list:
    print "i found it"

Answered by tm-

Post is based on