Python 在列表中查找属性等于某个值(满足任何条件)的对象
我有一张物品清单。我想在此列表中找到一个(第一个或其他)属性(或方法结果-其他)等于Python 在列表中查找属性等于某个值(满足任何条件)的对象,python,django,list,Python,Django,List,我有一张物品清单。我想在此列表中找到一个(第一个或其他)属性(或方法结果-其他)等于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(1
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 it's anywhere near 'Pythonic'
for x in test_list:
if x.value == value:
print "i found it!"
break
我认为使用生成器和reduce()
不会有任何区别,因为它仍然会遍历列表
注:value
的等式只是一个例子。当然,我们想要得到满足任何条件的元素
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
朴素的循环中断版本,是完美的python——它简洁、清晰、高效。要使其与一个衬里的行为相匹配,请执行以下操作:
for x in test_list:
if x.value == value:
print("i found it!")
break
else:
x = None
如果你不把
从循环中分离出来,这将None
分配给x
。我刚刚遇到了一个类似的问题,并为列表中没有对象满足要求的情况设计了一个小的优化(对于我的用例,这导致了性能的重大改进):
除了列表test_list之外,我还保留了一个额外的set test_value_set,它由我需要过滤的列表的值组成。因此,这里agf解决方案的其他部分变得非常快。因为它并不是为了完成而被提及的。
好的ol'过滤器可以过滤你的待过滤元素
函数式编程ftw。
您还可以通过测试
类的方法实现丰富的比较,并在
操作符中使用。
不确定这是否是最好的独立方式,但如果您需要基于其他地方的值比较测试
实例,这可能很有用
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"
对于下面的代码,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
xGen:pass=1结果=(12,2)
yFilt:pass=1结果=(12,2)
xGen:pass=2结果=(13,2)
yFilt:pass=2结果=(13,2)
xGen:通过=3结果=无
回溯(最近一次呼叫最后一次):
文件“test.py”,第12行,在
打印('yFilt:pass=',i',result=',next(yFilt))
停止迭代
您可以这样做
dict = [{
"id": 1,
"name": "Doom Hammer"
},
{
"id": 2,
"name": "Rings ov Saturn"
}
]
for x in dict:
if x["id"] == 2:
print(x["name"])
这就是我用来在一长串对象中查找对象的方法。一个简单的例子:
我们有以下数组
li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]
现在,我们要在数组中找到id等于1的对象
在列表理解中使用方法next
使用列表理解并返回第一项
自定义函数
输出上述所有方法都是{'id':1,'name':'ronaldo'}
旧问题,但我经常使用它(对于3.8版)。这有点语法上的盐,但它比最上面的答案有优势,因为您可以通过简单地删除[0]
来检索结果列表(如果有多个),如果没有找到,它仍然默认为None
。对于任何其他条件,只需将x.value==value
更改为您要查找的值即可
_[0] if (_:=[x for x in test_list if x.value==value]) else None
关于这个问题,这里有一个很好的讨论:原来的帖子荒谬地过时了,但是第二个回复与我的一行版本完全一致。我不认为它比基本的循环版本好。为了让人放心,“天真的循环中断版本,是完美的Pythonic”。这是一个很好的解决方案,但我如何修改你的行,使x.value实际上意味着x.fieldMemberName,该名称存储在value中?field=“name”下一步((如果x.field==value,则x代表test_列表中的x),无),因此在本例中,我实际上是在检查x.name,而不是x。field@StewartDale不完全清楚你在问什么,但我认为你的意思是。。。如果getattr(x,x.fieldMemberName)=值
。这将使用存储在fieldMemberName
中的名称从x
中获取属性,并将其与value
@ThatTechGuy进行比较--else
子句将位于for
循环中,而不是if
。(拒绝编辑)。@agf哇,我真的不知道它的存在。。酷!我很喜欢这种风格,但有两个潜在的问题。1:它只在Python 3中工作;在Python 2中,filter
返回一个与next
不兼容的列表。2:它要求有一个明确的匹配,否则您将得到一个StopIteration
异常。1:我不知道Python 2。当我开始使用Python时,Python 3已经可用了。不幸的是,我对Python 2的规范一无所知。2. @解放蜜蜂,正如agf所指出的。如果不喜欢异常,可以使用next(…,None)或其他一些默认值。我还将其作为注释添加到我的代码中。@freethebees第2点可能真的很好。当我需要列表中的某个对象时,快速失败是一件好事。@freethebees您不应该在2020年1月1日之后使用python 2,因为它是对它的支持的结束。@vrnvorona我的评论是在2018年发表的,这与提问者已经尝试过的有什么不同?我想展示他如何以最简单的方式获得对象和对象数组。
li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]
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)
_[0] if (_:=[x for x in test_list if x.value==value]) else None