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

Raf*_*l T 20 python search list find

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

class Mock:
    def __init__(self, name, age):
        self.name = name
        self.age = age
Run Code Online (Sandbox Code Playgroud)

然后我有一个包含这样的对象的列表:

myList = [Mock("Dan", 34), Mock("Jack", 30), Mock("Oli", 23)...]
Run Code Online (Sandbox Code Playgroud)

是否有一些内置功能,我可以获得年龄为30岁的所有模拟?当然,我可以对自己进行迭代并比较它们的年龄,但类似于

find(myList, age=30)
Run Code Online (Sandbox Code Playgroud)

会好的.有类似的东西吗?

dck*_*ney 35

你可以试试filter():

filter(lambda x: x.age == 30, myList)
Run Code Online (Sandbox Code Playgroud)

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

  • 如果你打算经常通过这个属性进行查找,你可能想要根据属性维护一个`dict`. (3认同)
  • 至少对于Python 3.5,您需要`list(filter(lambda x:x.age == 30,myList)))以获取列表。 (2认同)

Hug*_*ell 35

您可能想要预先索引它们 -

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]
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

X轴是myList中的Mocks数,Y轴是运行时的秒数.

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

  • 谢谢.和漂亮的图表.但讨论各种权衡,例如构建索引的额外启动时间以及它所需的空间,将会有所帮助. (3认同)

mar*_*ard 19

列表推导可以选择这些:

new_list = [x for x in myList if x.age == 30]
Run Code Online (Sandbox Code Playgroud)

  • 这里也对这个问题进行了一些很好的讨论:http://stackoverflow.com/a/1247490/317172 (2认同)

bea*_*rdc 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
Run Code Online (Sandbox Code Playgroud)

对于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)]
Run Code Online (Sandbox Code Playgroud)