Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Searching a list of objects in Python

Tags:

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.

like image 847
m0j0 Avatar asked Feb 28 '09 18:02

m0j0


People also ask

How do you find the object of a list in Python?

To find an element in the list, use the Python list index() method, The index() is an inbuilt Python method that searches for an item in the list and returns its index. The index() method finds the given element in the list and returns its position.

How do you filter a list of objects in Python?

Filter a Python List with filter() The filter(function, iterable) function takes a function as input that takes on argument (a list element) and returns a Boolean value whether this list element should pass the filter. All elements that pass the filter are returned as a new iterable object (a filter object).

Can you sort a list of objects in Python?

A simple solution is to use the list. sort() function to sort a collection of objects (using some attribute) in Python. This function sorts the list in-place and produces a stable sort. It accepts two optional keyword-only arguments: key and reverse.

How do you check if a list contains an item Python?

To check if the list contains an element in Python, use the “in” operator. The “in” operator checks if the list contains a specific item or not. It can also check if the element exists on the list or not using the list.


10 Answers

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
like image 57
Adam Rosenfield Avatar answered Oct 05 '22 09:10

Adam Rosenfield


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
like image 20
gahooa Avatar answered Oct 05 '22 11:10

gahooa


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!"
like image 35
Charlie Martin Avatar answered Oct 05 '22 09:10

Charlie Martin


[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
like image 23
Markus Jarderot Avatar answered Oct 05 '22 10:10

Markus Jarderot


filter(lambda x: x.n == 5, myList)
like image 45
vartec Avatar answered Oct 05 '22 10:10

vartec


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
like image 38
Tom Dunham Avatar answered Oct 05 '22 09:10

Tom Dunham


Another way you could do it is using the next() function.

matched_obj = next(x for x in list if x.n == 10)
like image 31
SEMICS Avatar answered Oct 05 '22 09:10

SEMICS


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
like image 22
Johannes Weiss Avatar answered Oct 05 '22 10:10

Johannes Weiss


Consider using a dictionary:

myDict = {}

for i in range(20):
    myDict[i] = i * i

print(5 in myDict)
like image 29
dan-gph Avatar answered Oct 05 '22 10:10

dan-gph


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)
like image 45
Matt Koch Avatar answered Oct 05 '22 11:10

Matt Koch