问题:在列表中查找属性等于某个值(满足任何条件)的对象
我有对象列表。我想在此列表中找到一个属性(或方法结果-任意)等于的(第一个或任何对象)对象value
。
找到它的最佳方法是什么?
这是测试用例:
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 isn't anywhere near 'Pythonic'
for x in test_list:
if x.value == value:
print "i found it!"
break
我认为使用生成器reduce()
不会有任何区别,因为它仍然会遍历list。
ps .:方程式to value
只是一个例子。当然我们要获得满足任何条件的元素。
I’ve got list of objects. I want to find one (first or whatever) object in this list that has attribute (or method result – whatever) equal to value
.
What’s is the best way to find 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!"
break
I think using generators and reduce()
won’t make any difference because it still would be iterating through list.
ps.: Equation to value
is just an example. Of course we want to get element which meets any condition.
回答 0
next((x for x in test_list if x.value == value), None)
这将从列表中获得与条件匹配的第一项,None
如果没有匹配项,则返回。这是我首选的单表达式形式。
然而,
for x in test_list:
if x.value == value:
print "i found it!"
break
天真的循环中断版本完全是Pythonic的-简洁,清晰和高效。为了使其与单线行为相匹配:
for x in test_list:
if x.value == value:
print "i found it!"
break
else:
x = None
如果您不在循环之外,这将分配None
给。x
break
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.
回答 1
由于尚未提及仅仅是为了完成。好的ol’过滤器可过滤您要过滤的元素。
函数编程
####### 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:\Users\mousavin\workspace\Scripts\test.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.
我知道通常在python列表中首选理解,或者至少这是我读到的,但是我不认为这个问题是诚实的。当然,Python不是FP语言,但是Map / Reduce / Filter完全可读,并且是函数式编程中最标准的标准用例。
所以你去了。了解您的函数式编程。
过滤条件列表
没有比这更容易的了:
next(filter(lambda x: x.val == value, my_unfiltered_list)) # Optionally: next(..., None) or some other default value to prevent Exceptions
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:\Users\mousavin\workspace\Scripts\test.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
回答 2
一个简单的例子:我们有以下数组
li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]
现在,我们要在数组中找到ID等于1的对象
next
列表理解的使用方法
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'}
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
next
with 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'}
回答 3
我遇到了一个类似的问题,针对列表中没有对象符合要求的情况设计了一个小型优化(对于我的用例,这导致了重大的性能改进):
与列表test_list一起,我还有一个额外的集合test_value_set,它由我需要过滤的列表的值组成。因此,这里的agf解决方案的其他部分变得非常快。
I just ran into a similar problem and devised a small optimization for the case where no object in the list meets the requirement.(for my use-case this resulted in major performance improvement):
Along with the list test_list, I keep an additional set test_value_set which consists of values of the list that I need to filter on. So here the else part of agf’s solution becomes very-fast.
回答 4
你可以做这样的事情
dict = [{
"id": 1,
"name": "Doom Hammer"
},
{
"id": 2,
"name": "Rings ov Saturn"
}
]
for x in dict:
if x["id"] == 2:
print(x["name"])
那就是我用来在长对象数组中查找对象的东西。
You could do something like this
dict = [{
"id": 1,
"name": "Doom Hammer"
},
{
"id": 2,
"name": "Rings ov Saturn"
}
]
for x in dict:
if x["id"] == 2:
print(x["name"])
Thats what i use to find the objects in a long array of objects.
回答 5
您还可以通过__eq__
方法为Test
类和use in
运算符实现丰富的比较。不知道这是否是最好的独立方法,但是如果您需要Test
基于value
其他地方比较实例,这可能会很有用。
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"
You could also implement rich comparison via __eq__
method for your Test
class and use in
operator.
Not sure if this is the best stand-alone way, but in case if you need to compare Test
instances based on value
somewhere else, this could be useful.
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"
回答 6
对于下面的代码,xGen是一个匿名生成器表达式,yFilt是一个过滤器对象。请注意,对于xGen,将在列表耗尽时返回附加的None参数,而不是抛出StopIteration。
arr =((10,0), (11,1), (12,2), (13,2), (14,3))
value = 2
xGen = (x for x in arr if x[1] == value)
yFilt = filter(lambda x: x[1] == value, arr)
print(type(xGen))
print(type(yFilt))
for i in range(1,4):
print('xGen: pass=',i,' result=',next(xGen,None))
print('yFilt: pass=',i,' result=',next(yFilt))
输出:
<class 'generator'>
<class 'filter'>
xGen: pass= 1 result= (12, 2)
yFilt: pass= 1 result= (12, 2)
xGen: pass= 2 result= (13, 2)
yFilt: pass= 2 result= (13, 2)
xGen: pass= 3 result= None
Traceback (most recent call last):
File "test.py", line 12, in <module>
print('yFilt: pass=',i,' result=',next(yFilt))
StopIteration
For below code, xGen is an anonomous generator expression, yFilt is a filter object. Note that for xGen the additional None parameter is returned rather than throwing StopIteration when the list is exhausted.
arr =((10,0), (11,1), (12,2), (13,2), (14,3))
value = 2
xGen = (x for x in arr if x[1] == value)
yFilt = filter(lambda x: x[1] == value, arr)
print(type(xGen))
print(type(yFilt))
for i in range(1,4):
print('xGen: pass=',i,' result=',next(xGen,None))
print('yFilt: pass=',i,' result=',next(yFilt))
Output:
<class 'generator'>
<class 'filter'>
xGen: pass= 1 result= (12, 2)
yFilt: pass= 1 result= (12, 2)
xGen: pass= 2 result= (13, 2)
yFilt: pass= 2 result= (13, 2)
xGen: pass= 3 result= None
Traceback (most recent call last):
File "test.py", line 12, in <module>
print('yFilt: pass=',i,' result=',next(yFilt))
StopIteration