在列表中找到属性等于某个值的对象(满足任意条件)

407 投票
10 回答
457631 浏览
提问于 2025-04-16 23:58

我有一个对象列表。我想在这个列表中找到一个(第一个或者其他的)对象,这个对象有一个属性(或者方法的结果)等于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的等式只是个例子。当然,我们想要找到满足任何条件的元素。

10 个回答

39

因为没有提到,所以我补充一下。老掉牙的过滤器,用来过滤你想要筛选的元素。

函数式编程真不错。

####### 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并不是一个纯粹的函数式编程语言,但Map、Reduce和Filter这些方法都很容易理解,而且在函数式编程中是最常见的用法。

所以,了解一下函数式编程吧。

过滤条件列表

这不会再简单了:

next(filter(lambda x: x.val == value,  my_unfiltered_list)) # Optionally: next(..., None) or some other default value to prevent Exceptions
40

一个简单的例子:

我们有一个这样的数组:

li = [{"id":1,"name":"ronaldo"},{"id":2,"name":"messi"}]

现在,我们想在这个数组中找到一个id等于1的对象。

  1. 使用方法 next 和列表推导式。
next(x for x in li if x["id"] == 1 )
  1. 使用列表推导式并返回第一个项目。
[x for x in li if x["id"] == 1 ][0]
  1. 自定义函数。
def find(arr , id):
    for x in arr:
        if x["id"] == id:
            return x
find(li , 1)

以上所有方法的输出结果是 {'id': 1, 'name': 'ronaldo'}

771
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

如果你没有在循环中使用break跳出循环,这样会把None赋值给x

撰写回答