22

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

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)

会好的。有没有类似的东西?

4

4 回答 4

36

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

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 轴后面的绿点是我的索引;-)
于 2012-06-01T23:44:32.920 回答
35

你可以试试filter()

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

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

于 2012-06-01T23:39:21.557 回答
21

列表推导可以选择这些:

new_list = [x for x in myList if x.age == 30]
于 2012-06-01T23:40:30.973 回答
5

列表推导式几乎总是做这些事情的更快方法(这里的速度是 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)]
于 2012-06-02T00:50:51.890 回答