Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在列表中查找属性等于某个值(满足任何条件)的对象_Python_Django_List - Fatal编程技术网

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