2009-02-28 168 views
50

我們假設我正在創建一個類似於C風格結構的簡單類來保存數據元素。我試圖找出如何搜索具有等於某個特定值的屬性的對象列表。下面是一個簡單的例子來說明我正在嘗試做什麼。在Python中搜索對象列表

例如:

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功能都不適用於我。

+0

也許你的實例的無意夸克:myList中= [數據()N == 0,數據()N = 1。 ,...]其中data.n將由range()和data.n分配,這將成爲myList的索引。因此,您只需通過索引值引用myList即可啓動任何Data()實例。當然,你以後可以修改myList [0] .n = 5.2或其他東西。這個例子可能過於簡單了。 – DevPlayer 2016-12-22 15:48:18

回答

66

你可以得到所有匹配的元素與列表理解列表:

[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 
+19

或任何(custom_filter(x)for myList中的x,如果x.n == 30),這只是您的「contains」函數作爲內建函數。 – nosklo 2009-02-28 20:12:04

+0

nosklo上的語法錯誤 - 在生成器周圍需要一組額外的()。 – gahooa 2009-02-28 20:16:24

+0

並非如此。試試看看。 – 2009-03-01 04:30:19

1

您應該添加__eq____hash__方法您Data類,它可以檢查__dict__屬性是相等的(相同的屬性),然後如果他們的價值是相等的,太。

如果你這樣做,你可以使用

test = Data() 
test.n = 5 

found = test in myList 

in關鍵字檢查testmyList

如果你只想在Data AA n屬性,你可以使用:

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 
25
[x for x in myList if x.n == 30]    # list of all 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 
+0

這是一個很好的答案,因爲「第一個」方法可能是最常見的用例。 – galarant 2013-01-28 22:01:43

36

只是爲了保持完整性,讓我們不要忘記最簡單的事情能夠工作:

for i in list: 
    if i.n == 5: 
    # do something with it 
    print "YAY! Found one!" 
24
filter(lambda x: x.n == 5, myList) 
7

您可以使用in尋找一個項目集合中,和列表理解來提取你感興趣的領域。這適用於列表,集合,元組和任何定義爲__contains____getitem__的東西。

if 5 in [data.n for data in myList]: 
    print "Found it" 

參見:

46

古樸,典雅,功能強大:

和內建的一起選擇生成表達式...( PYT漢2.5+)

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

使用Python any()內置,其被定義如下:

任何(迭代)-> 返回真,如果迭代的任何元素是真實的。等效於:

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

考慮使用的字典:

myDict = {} 

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

print(5 in myDict)