next((x for x in test_list if x.value == value), None)
This gets the first item from the list that matches the condition, and returns None if no item matches. It's my preferred single-expression form.
However,
for x in test_list:
if x.value == value:
print("i found it!")
break
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!")
break
else:
x = None
This will assign None to x if you don't break out of the loop.
next((x for x in test_list if x.value == value), None)
This gets the first item from the list that matches the condition, and returns None if no item matches. It's my preferred single-expression form.
However,
for x in test_list:
if x.value == value:
print("i found it!")
break
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!")
break
else:
x = None
This will assign None to x if you don't break out of the loop.
A simple example: We have the following array
li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]
Now, we want to find the object in the array that has id equal to 1
- Use method
nextwith list comprehension
next(x for x in li if x["id"] == 1 )
- Use list comprehension and return first item
[x for x in li if x["id"] == 1 ][0]
- Custom Function
def find(arr , id):
for x in arr:
if x["id"] == id:
return x
find(li , 1)
Output all the above methods is {'id': 1, 'name': 'ronaldo'}
Get list item by attribute in Python - Stack Overflow
python - How do i access and object attribute inside a list of objects given certain index? - Stack Overflow
Searching a list of objects in Python - Stack Overflow
flask - How to find object in python list by attribute - Stack Overflow
What is the best way to find objects in a list in Python?
Can I find multiple objects using one of these methods?
Is there a performance difference between the methods?
Hey, so I'm coding up a discord bot, where I have a list of Objects (discord.CategoryChannel() is the class)
all these objects have an attribute 'name' which is a string
I need to return the object who's 'name' attribute is 'Temp VCs'
I have figured out that I can use any() to find if such an object exists in the list whose 'name' is 'Temp VCs'
However what method can I use (apart from the brute force way of writing a for loop and an if statement inside it) to return the object which has its attribute 'name' equal to 'Temp VCs'
Yes, you loop and compare:
items = [item for item in container if item.attribute == value]
And you get back a list which can be tested to see how many you found.
If you will be doing this a lot, consider using a dictionary, where the key is the attribute you're interested in.
If you do this it only gives the very first match, instead of comparing the whole list: find first sequence item that matches a criterion.
If you do something like this, you don't have to catch the exception but get None instead:
item = next((i for i in items if i == 'value'), None)
In Python, to access object attribute the syntax is
<object instance>.<attribute_name>
In your case, [index].
As Paul said, use dir(<object_instance>[index]) to get all attribute, methods associated object instance.
You can also use for loop to iterate over
for <obj> in <object_list>:
<obj>.<attribute_name>
Hope it helps
You can access the dict (a.k.a Hashtable) of all attributes of an object with:
ListObj[i].__dict__
Or you can only get the names of these attributes as a list with either
ListObj[i].__dict__.keys()
and
dir(ListObj[i])
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
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
If you define __hash__ in your soldier class to return the soldier id and define __eq__ to test for id equality, you could try something like this:
user.soldiers = list(set(user.soldiers + soldierlist))
So, somewhere in your soldier class:
def __hash__(self):
return self.id
def __eq__(self, other):
return self.id == other.id
Here is an approach which avoids constantly rescanning the list
current_ids = set(soldier.id for soldier in user.soldiers)
for soldier_class in soldierlist:
if soldier_class.id not in current_ids:
user.soldiers.append( soldier_class() )
By storing all the ids in set, looking them up can be done much faster then just rescanning through the list.
I have a rather simple question but I haven't been able to find an answer so far: if I have a 2D list of objects, how can I extract all the values from a common attribute?
This is some class:
class Foo():
def __init__(self, attr):
self.attr = attrFor a 1D list, it's really simple:
array = [Foo(i) for i in range(6)] [obj.attr for obj in array]
This will display: [0, 1, 2, 3, 4, 5].
For a multidimensional list, though, this won't work. A solution would be using loops or lists of comprehension to extract the attributes from each column or line. However, slices allow us to access a specific region of a multidimensional list.
So, let's say you have a 6x6 list (or ndarray) of objects, and you want to access the attributes at [4:,4:], or even better, you want to slice the list in a non-contiguous way and then get the attributes of all object elements in the pattern. Is that possible?
Check this image from the numpy docs to have a visual reference about what I'm talking about (see 2nd and 4th slices).
I'm aiming at being able to use this for a board game in which the board would be sliced into different "tile" groups or patterns and then check the properties of the objects in those tiles.
This is not homework.
One option is to use the next() built-in:
dave = next(person for person in a.pList if person.num == 123)
This will throw StopIteration if nothing is found. You can use the two-argument form of next() to provide a default value for that case:
dave = next(
(person for person in a.pList if person.num == 123),
None,
)
A slightly more verbose alternative is a for loop:
for person in a.pList:
if person.num == 123:
break
else:
print "Not found."
person = None
dave = person
If those nom's are unique keys, and all you are ever going to do is access your persons using this unique key you should indeed rather use a dictionary.
However if you want to add more attributes over time and if you like to be able to retrieve one or more person by any of those attributes, you might want to go with a more complex solution:
class Example():
def __init__(self):
self.__pList = []
def addPerson(self,name,number):
self.__pList.append(Person(name,number))
def findPerson(self, **kwargs):
return next(self.__iterPerson(**kwargs))
def allPersons(self, **kwargs):
return list(self.__iterPerson(**kwargs))
def __iterPerson(self, **kwargs):
return (person for person in self.__pList if person.match(**kwargs))
class Person():
def __init__(self,name,number):
self.nom = name
self.num = number
def __repr__(self):
return "Person('%s', %d)" % (self.nom, self.num)
def match(self, **kwargs):
return all(getattr(self, key) == val for (key, val) in kwargs.items())
So let's assume we got one Mike and two Dave's
a = Example()
a.addPerson('dave',123)
a.addPerson('mike',345)
a.addPerson('dave',678)
Now you can find persons by number:
>>> a.findPerson(num=345)
Person('mike', 345)
Or by name:
>>> a.allPersons(nom='dave')
[Person('dave', 123), Person('dave', 678)]
Or both:
>>> a.findPerson(nom='dave', num=123)
Person('dave', 123)
To handle the last element, you can use modulo: index % len(users).
Here is one way:
def find_after_name(users, name):
for i, user in enumerate(users):
if user.name == name:
return users[(i+1) % len(users)]
Another option would be to zip the list with a shifted copy of the list. deque.rotate() is useful for such shifting:
from collections import deque
def find_after_name(users, name):
users2 = deque(users)
users2.rotate(-1)
for user1, user2 in zip(users1, users2):
if user1.name == name:
return user2
Since you've chosen to use OOP, why not implement a UserList class inherited from built-in list class?
class User(object):
def __init__(self, name):
self.name = name
def __str__(self):
return repr(self)
def __repr__(self):
return "User('{0}')".format(self.name)
class UserList(list):
def find(self, name):
for k, user in enumerate(self):
if user.name == name:
return k, user
def next_to(self, name):
"""get user next to the one of name (e.g. 'James')"""
index, user = self.find(name)
next_to_index = self.get_next_to_index(index)
return self[next_to_index]
def get_next_to_index(self, index):
next_to_index = index + 1
if next_to_index == len(self):
# meaning index is already the last element, need to reset index
next_to_index = 0
return next_to_index
users = UserList()
users.append(User("Peter"))
users.append(User("James"))
users.append(User("John"))
print users.find('James')
print users.next_to('James')
print users.next_to('John')
Output:
(1, User('James'))
User('John')
User('Peter')