在python的List中通过其成员查找对象

Posted

技术标签:

【中文标题】在python的List中通过其成员查找对象【英文标题】:Find object by its member inside a List in python 【发布时间】:2012-06-07 04:25:40 【问题描述】:

让我们假设以下简单对象:

class Mock:
    def __init__(self, name, age):
        self.name = name
        self.age = age

然后我有一个列表,其中包含一些像这样的对象:

myList = [Mock("Dan", 34), Mock("Jack", 30), Mock("Oli", 23)...]

是否有一些内置功能可以让我获得所有年龄为 30 岁的 Mocks? 当然我可以遍历他们并比较他们的年龄,但是像

find(myList, age=30)

会很好。有这样的吗?

【问题讨论】:

【参考方案1】:

你可以试试filter():

filter(lambda x: x.age == 30, myList)

这将返回一个列表,其中仅包含满足 lambda 表达式的对象。

【讨论】:

如果您打算经常通过此属性进行查找,您可能希望基于该属性维护一个dict 至少对于 Python 3.5,你需要list(filter(lambda x: x.age == 30, myList)) 来获取列表。 使用 filter() 是旧的经典答案,但列表推导式在 Python 版本之间更快且更便携,如其他答案中所述。【参考方案2】:

列表推导可以选择这些:

new_list = [x for x in myList if x.age == 30]

【讨论】:

也是不错的解决方案,但@dcrooney 答案更适合该功能。有没有人比较什么更快? timeit 在我的机器上为列表理解提供了大约 0.30 微秒,为 lambda 过滤器提供了 0.58 微秒。但它们在这里基本上是等价的,所以你应该使用你喜欢的那个。 这里也对这个问题进行了一些很好的讨论:***.com/a/1247490/317172【参考方案3】:

您可能希望对它们进行预索引 -

from collections import defaultdict

class Mock(object):
    age_index = defaultdict(list)

    def __init__(self, name, age):
        self.name = name
        self.age = age
        Mock.age_index[age].append(self)

    @classmethod
    def find_by_age(cls, age):
        return Mock.age_index[age]

编辑:一张图片胜过千言万语:

X 轴是 myList 中的 Mocks 数量,Y 轴是运行时间,以秒为单位。

红点是@dcrooney 的 filter() 方法 蓝点是@marshall.ward 的列表理解 隐藏在 X 轴后面的绿点是我的索引 ;-)

【讨论】:

非常感谢您的回答。我正要手动重新实现类似的东西。 谢谢。和漂亮的图表。但讨论各种权衡会有所帮助,例如建立索引的额外启动时间,以及它所需的空间。 这是一个很好的解决方案,但您确实会冒以下风险:1. 更高的内存使用率 2. 更多的 CPU 使用率来预计算列表。对于大型列表,这可能会令人望而却步。【参考方案4】:

列表推导式几乎总是做这些事情的更快方法(这里是 2 倍),尽管如前所述,如果您关心速度,索引会更快。

~$ python -mtimeit -s"from mock import myList" "filter(lambda x: x.age==21, myList)"
1000000 loops, best of 3: 1.34 usec per loop
~$ python -mtimeit -s"from mock import myList" "[x for x in myList if x.age==21]"
1000000 loops, best of 3: 0.63 usec per loop

对于当前目录下的文件mock.py

class Mock:
    def __init__(self, name, age):
        self.name = name
        self.age = age

myList = [Mock('Tom', 20), Mock('Dick', 21), Mock('Harry', 21), Mock('John', 22)]

【讨论】:

以上是关于在python的List中通过其成员查找对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用python在selenium中通过其id名称的一部分查找元素

如何使用存储库接口在 Spring Data 中通过其嵌套对象的 objectId 查找集合?

在python中通过其相似性进行图像聚类

如何在sum()语句中通过其位置引用data.table的列

在 Rails 中通过其 belongs_to 关系查询记录

如何在C ++中通过其名称获取进程句柄?