2014-02-22 68 views
3

我目前正在尋找一種方法來將列表中的元素從左到右進行比較。Python:將列表中的元素彼此進行比較

這裏是我的清單:

mylist = [[15], [14, 15], [19, 20], [13], [3], [65, 19], [19, 20, 31]] 

我需要的第一個元素比較所有其他人,並檢查是否有任何值匹配,同樣的事情第二個和第三個元素等等,直到它到達名單末尾。如果有匹配,我需要打印出來。我需要打印出匹配的值以及匹配的索引。

例如。

index 0 matched with index 1 for value 15. 
index 2 matched with index 5 for value 19 
index 2 matched with index 6 for value 19 
index 2 matched with index 6 for value 20 
index 5 matched with index 6 for value 19. 

我該如何去做這件事?

+0

@kroolik,感謝您的快速回復。我想也許我應該將列表中的每個元素轉換爲一個集合。然後使用相交來比較每個集合。如果有匹配的值,那麼我會打印匹配值和它匹配的索引。你對這種方法有什麼看法?我遠嗎?或關閉?謝謝你的幫助。 – noahandthewhale

+0

@kroolik,或許這可能對我有幫助? http://stackoverflow.com/questions/16603282/how-to-compare-each-item-in-a-list-with-the-rest-only-once – noahandthewhale

+0

你可以嘗試@arshajii的解決方案 - 非常有效,易於實現,並且非常直接瞭解。 –

回答

2
mylist = [[15], [14, 15], [19, 20], [13], [3], [65, 19], [19, 20, 31]] 
my_set_list = [set(item) for item in mylist] 
for i1, item in enumerate(my_set_list): 
    for i2 in xrange(i1 + 1, len(my_set_list)): 
     for val in (item & my_set_list[i2]): 
      print "Index {} matched with index {} for value {}".format(i1,i2,val) 

輸出

Index 0 matched with index 1 for value 15. 
Index 2 matched with index 5 for value 19. 
Index 2 matched with index 6 for value 19. 
Index 2 matched with index 6 for value 20. 
Index 5 matched with index 6 for value 19. 
+0

對於大型列表,這將表現不佳。 – arshajii

+0

@arshajii我也這麼認爲,但我的名單最多隻有175個元素。所以我認爲這種做法可能沒問題。 – noahandthewhale

3

天真的解決方案是在循環的每對,這是緩慢的。但是,你可以做一些沿的臺詞:

  • 創建一個字典,將映射整數(在你的嵌套列表元素)包含列表的指數在你的主人名單。
  • 循環遍歷主列表,併爲每個子列表添加索引到與dict中每個元素相對應的位置。
  • 現在,字典的值由兩個元素爲「對」的列表組成。

這就是我的意思是:

>>> mylist = [[15], [14, 15], [19, 20], [13], [3], [65, 19], [19, 20, 31]] 
>>> 
>>> pairs = dict() 
>>> 
>>> 
>>> from collections import defaultdict 
>>> 
>>> pairs = defaultdict(list) 
>>> 
>>> for idx, sub in enumerate(mylist): 
...  for a in sub: 
...   pairs[a].append(idx) 
... 
>>> pairs 
defaultdict(<type 'list'>, {65: [5], 3: [4], 13: [3], 14: [1], 15: [0, 1], 19: [2, 5, 6], 20: [2, 6], 31: [6]}) 

你可以只用1元無視值列表(因爲那意味着我們沒有一對)。帶有2+元素的元素形成各種配對。例如與19我們有[2, 5, 6]含義:

  • 2和5是一對
  • 2和6是一對
  • 5和6是一對

你有。這種方法對於嵌套列表中的項目總數是線性的。如果您在嵌套列表長度上有一個合理的上限,那麼這是主列表大小中的O(n)。

現在的輸出:

>>> from itertools import combinations 
>>> 
>>> for k,v in pairs.iteritems(): 
...  if len(v) > 1: 
...   for a,b in combinations(v, 2): 
...    print "Index {} matched with index {} for value {}".format(a, b, k) 
... 
Index 0 matched with index 1 for value 15 
Index 2 matched with index 5 for value 19 
Index 2 matched with index 6 for value 19 
Index 5 matched with index 6 for value 19 
Index 2 matched with index 6 for value 20 
+0

我會試試這個 – noahandthewhale

+0

+1我喜歡這個主意,但這可能無法維持秩序。 – thefourtheye

+0

@Chrinna查看更新,其中包括如何生成所需的輸出。訂單在這裏重要嗎? – arshajii

3

您可以使用itertools.combinations,這樣可以節省您從嵌套循環:

In [770]: l2=[(i,set(mylist[i])) for i in range(len(mylist))] 
    ...: for (i, a), (j, b) in combinations(l2,2): 
    ...:  for v in a.intersection(b): 
    ...:   print "Index {} matched with index {} for value {}".format(i,j,v) 
Index 0 matched with index 1 for value 15 
Index 2 matched with index 5 for value 19 
Index 2 matched with index 6 for value 19 
Index 2 matched with index 6 for value 20 
Index 5 matched with index 6 for value 19