2016-05-19 49 views
2

我有一個元組列表,如li = [('aa', 'bb'), ('bb','cc'), ('dd', 'ee')]。從li我想產生一個元組對,其中li中的一個元組的第一個元素等於另一個元素li中的第二個元素。在本文的例子中,輸出列表將包括一對元組的列表:將對的列表轉換爲與第一個或最後一個項目共享的對的列表對

[(('aa', 'bb'), ('bb', 'cc'))] 

這是短li列表很容易。我已經做了,例如通過類似

joints = [] 
for pair in itertools.permutations(li, r=2): 
    if pair[0][1] == pair[1][0]: 
     joints += ((pair[0][0], pair[0][1]), (pair[1][0], pair[1][1])) 

然而,隨着一長串li所有長度爲2的排列總數迅速爆炸,變得難以管理。

我認爲必須有一個更可行的方法來做到這一點,也許使用矩陣乘法或哈希表。什麼是更長時間(例如5000長度)列表的合理方式?

+1

「拓撲排序」 –

+0

怎麼樣重複的情況下,和元組可以匹配兩種情況? – Kasramvd

+0

@Kasramvd在'li'中沒有重複,但是每個元素都可以與許多其他元素相匹配。 – Hatshepsut

回答

2

您可以使用字典,以收集預期的對。而作爲一個更Python的方法,你可以使用defaultdict()deque功能從collections模塊,以保持每對有關對在deque

>>> from collections import defaultdict, deque 
>>> d = defaultdict(deque) 

>>> for i, j in li: 
...  for k, t in li: 
...  if (i, j) != (k, t) and (i == t or j == k): 
...    d[(i, j)].append((k, t)) 
... 
>>> 
>>> d 
defaultdict(<type 'collections.deque'>, 
      {('dd', 'ee'): deque([('ee', 'mm')]), 
      ('rr', 'cc'): deque([('cc', 'tt')]), 
      ('cc', 'tt'): deque([('bb', 'cc'), ('rr', 'cc')]), 
      ('aa', 'bb'): deque([('bb', 'cc')]), 
      ('ee', 'mm'): deque([('dd', 'ee')]), 
      ('bb', 'cc'): deque([('aa', 'bb'), ('cc', 'tt')])}) 

和創建你可以使用一個元組的願望清單列表理解,通過循環詞典詞條:

>>> [[(k, v) for v in values] for k, values in d.items()] 
[[(('dd', 'ee'), ('ee', 'mm'))], [(('rr', 'cc'), ('cc', 'tt'))], [(('cc', 'tt'), ('bb', 'cc')), (('cc', 'tt'), ('rr', 'cc'))], [(('aa', 'bb'), ('bb', 'cc'))], [(('ee', 'mm'), ('dd', 'ee'))], [(('bb', 'cc'), ('aa', 'bb')), (('bb', 'cc'), ('cc', 'tt'))]] 

注意,你可以簡單地使用list爲您defaultdict的功能,如果你不想做的結果沒有任何額外的操作,但是如果你想要做的更多的操作結果就像彈出,在兩邊追加,旋轉等。deque是一個不錯的選擇,因爲它爲大多數操作提供了不變的順序。

更簡潔的方式通過itertools.permutations

>>> from itertools import permutations 
>>> for i, j permutations(li, 2): 
...  if (i == t or j == k): 
...    d[(i, j)].append((k, t)) 
+0

謝謝,這非常好。如果我明白你在說什麼,我認爲我想要的條件實際上是'j == k'而不是'(i == t或j == k)''。我打算讓命令變得有意義:從'[('a','b'),'''','c')]'我想產生'(('''','b'), ('','c'),('a','b'))''。 – Hatshepsut

+0

@Hatshepsut你的問題含糊不清,隨意根據你的需要改變它;-)。 – Kasramvd

0

保持兩套 - 第一指數的元素和第二指數的元素。從原始列表中,只添加至少有一個元素在這兩個集合中的元組。

li = [('aa', 'bb'), ('bb','cc'), ('dd', 'ee')] 

first_pos = {x for x, y in li} 
second_pos = {y for x, y in li} 

arr = [(x, y) for x, y in li if (x in first_pos and x in second_pos) or (y in 
    first_pos and y in second_pos)] 

print(arr) 

輸出 -

[('aa', 'bb'), ('bb', 'cc')] 
相關問題