2010-04-01 113 views
14

我有一個Python對象列表。然後我有另一個對象列表。我想通過第一個列表,看看是否有任何項目出現在第二個列表中。Python檢查對象是否在對象列表中

我想我可以簡單地做

for item1 in list1: 
    for item2 in list2: 
     if item1 == item2: 
      print "item %s in both lists" 

然而,這似乎並沒有工作。雖然如果我這樣做:

if item1.title == item2.title: 

它的作品沒關係。我有比這更多的屬性,儘管如此,如果我不需要比較所有的屬性,那麼我不想做大的if語句。

任何人都可以給我幫助或建議我可以做什麼來找到出現在兩個列表中的對象。

謝謝

回答

24

假設你的對象只有一個title屬性,是相關的平等,就必須實現__eq__方法如下:

class YourObject: 
    [...] 
    def __eq__(self, other): 
     return self.title == other.title 

當然,如果你有更多的屬性,這些屬性是相關的平等,你也必須包括這些。您也可以考慮實施__ne____cmp__以獲得一致的行爲。誰出現在兩個列表

5

set intersection將做到這一點。

>>> x=[1,2,3,4] 
>>> y=[3,4,5,6] 
>>> for i in set(x) & set(y): 
...  print "item %d in both lists" %i 
... 
item 3 in both lists 
item 4 in both lists 
+3

我認爲他的問題是對象平等,而不是發現:) – extraneon 2010-04-01 08:39:47

+3

OP有對象列表,而不是原子類型列表。如果你使用沒有定義'__hash__'的對象來嘗試你的代碼,它將不起作用,就像OP的代碼不能處理沒有定義'__eq__'或'__cmp__'的對象列表一樣。 – hughdbrown 2010-04-01 15:05:44

9

如果對象是不一樣的情況下,你需要實現__eq__方法蟒蛇是能夠告訴當2個對象實際上是相等的。

當然,大多數庫類型(例如字符串和列表)已經實現了__eq__,這可能是比較標題對您有用的原因(它們是字符串嗎?)。

欲瞭解更多信息,請參閱python documentation
這是__eq__random example

+0

是的,他們不是同一個例子。你可以給我一個__eq__函數的例子,因爲我對Python很陌生 – John 2010-04-01 08:41:23

+0

@John - 我已經添加了一個示例鏈接。只要搜索谷歌代碼搜索「def __eq__」爲我解決了它:) – abyx 2010-04-01 08:46:02

4

尋找對象:

l1 = [1,2,3,4,5] 
l2 = [3,4,5] 
common = set(l1).intersection(set(l2)) 

__eq__實施對象上結合這爲其他建議。

0

嘗試以下操作:

list1 = [item1, item2, item3] 
list2 = [item3, item4, item5] 
for item in list1: 
    if item in list2: 
     print "item %s in both lists" % item 
2
matches = [x for x in listA if x in listB] 
+0

除非我誤解'in'是如何工作的,其運行時間將是列表長度的產物,這可能是不好的。 – shabbychef 2010-04-01 18:50:06

3

你需要寫一個__eq__功能來定義如何比較對象是否相等。如果你想排序,那麼你應該有一個__cmp__函數,並且按照__cmp__來實現__eq__是最有意義的。

def __eq__(self, other): 
    return cmp(self, other) == 0 

你或許應該還實現__hash__,你絕對應該,如果你打算把你的對象爲一組或字典。對象的默認__hash__是id(),它有效地使所有對象都是唯一的(即唯一性不基於對象內容)。

我爲一種類型的等價比較寫了一個基類/接口。你可能會發現它有用:

class Comparable(object): 
    def attrs(self): 
     raise Exception("Must be implemented in concrete sub-class!") 
    def __values(self): 
     return (getattr(self, attr) for attr in self.attrs()) 
    def __hash__(self): 
     return reduce(lambda x, y: 37 * x + hash(y), self.__values(), 0) 
    def __cmp__(self, other): 
     for s, o in zip(self.__values(), other.__values()): 
      c = cmp(s, o) 
      if c: 
       return c 
     return 0 
    def __eq__(self, other): 
     return cmp(self, other) == 0 
    def __lt__(self, other): 
     return cmp(self, other) < 0 
    def __gt__(self, other): 
     return cmp(self, other) > 0 

if __name__ == '__main__': 
    class Foo(Comparable): 
     def __init__(self, x, y): 
      self.x = x 
      self.y = y 
     def attrs(self): 
      return ('x', 'y') 
     def __str__(self): 
      return "Foo[%d,%d]" % (self.x, self.y) 

    def foo_iter(x): 
     for i in range(x): 
      for j in range(x): 
       yield Foo(i, j) 

    for a in foo_iter(4): 
     for b in foo_iter(4): 
      if a<b: print "%(a)s < %(b)s" % locals() 
      if a==b: print "%(a)s == %(b)s" % locals() 
      if a>b: print "%(a)s > %(b)s" % locals() 

派生類必須實現attrs()返回有助於其身份(即不變的屬性,使得它它是什麼)對象的屬性的元組或列表。最重要的是,代碼在存在多個屬性的情況下正確處理等同性,這是舊學校代碼,通常不正確。