在Python中搜索对象列表

时间:2009-02-28 18:06:20

标签: python

让我们假设我正在创建一个类似于C风格结构的简单类,只保存数据元素。我试图弄清楚如何搜索对象列表中具有等于某个值的属性的对象。下面是一个简单的例子来说明我正在尝试做的事情。

例如:

class Data:
    pass

myList = []

for i in range(20):
    data = Data()
    data.n = i
    data.n_squared = i * i
    myList.append(data)

如何搜索myList列表以确定它是否包含n == 5的元素?

我一直在谷歌搜索和搜索Python文档,我想我可以用列表理解来做到这一点,但我不确定。我可能会补充一点,我必须使用Python 2.4.3,所以我无法使用任何新的gee-whiz 2.6或3.x功能。

10 个答案:

答案 0 :(得分:98)

您可以通过列表理解获取所有匹配元素的列表:

[x for x in myList if x.n == 30]  # list of all elements with .n==30

如果您只是想确定列表是否包含匹配的任何元素并且(相对)有效地执行,那么您可以

def contains(list, filter):
    for x in list:
        if filter(x):
            return True
    return False

if contains(myList, lambda x: x.n == 3)  # True if any element has .n==3
    # do stuff

答案 1 :(得分:59)

简单,优雅,强大:

生成器表达式与内置...(python 2.5 +)

any(x for x in mylist if x.n == 10)

使用Python any()内置,定义如下:

  

任意(可迭代) ->   如果iterable的任何元素为true,则返回True。相当于:

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

答案 2 :(得分:42)

为了完整,我们不要忘记可能有效的最简单的事情:

for i in list:
  if i.n == 5:
     # do something with it
     print "YAY! Found one!"

答案 3 :(得分:31)

[x for x in myList if x.n == 30]               # list of all matches
[x.n_squared for x in myList if x.n == 30]     # property of matches
any(x.n == 30 for x in myList)                 # if there is any matches
[i for i,x in enumerate(myList) if x.n == 30]  # indices of all matches

def first(iterable, default=None):
  for item in iterable:
    return item
  return default

first(x for x in myList if x.n == 30)          # the first match, if any

答案 4 :(得分:27)

filter(lambda x: x.n == 5, myList)

答案 5 :(得分:8)

您可以使用in查找集合中的项目,使用列表解析来提取您感兴趣的字段。这(适用于列表,集合,元组和任何定义{{1 }或__contains__)。

__getitem__

另见:

答案 6 :(得分:3)

您应该向__eq__课程添加__hash__Data方法,它可以检查__dict__属性是否相等(相同属性),然后是价值也是相等的。

如果你这样做,你可以使用

test = Data()
test.n = 5

found = test in myList

in关键字会检查test是否在myList

如果您只想使用n中的Data属性,则可以使用:

class Data(object):
    __slots__ = ['n']
    def __init__(self, n):
        self.n = n
    def __eq__(self, other):
        if not isinstance(other, Data):
            return False
        if self.n != other.n:
            return False
        return True
    def __hash__(self):
        return self.n

    myList = [ Data(1), Data(2), Data(3) ]
    Data(2) in myList  #==> True
    Data(5) in myList  #==> False

答案 7 :(得分:3)

考虑使用字典:

myDict = {}

for i in range(20):
    myDict[i] = i * i

print(5 in myDict)

答案 8 :(得分:2)

另一种方法是使用next()函数。

matched_obj = next(x for x in list if x.n == 10)

答案 9 :(得分:0)

也许下面的列表推导结合索引方法?

data_n = 30
j = [data.n for data in mylist].index[data_n]
mylist[j].data.n == data_n