我有一个像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 +长度)列表的合理方法是什么?
答案 0 :(得分:2)
您可以使用字典,以收集预期的对。作为更加pythonic的方法,您可以使用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))
答案 1 :(得分: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')]