根据路由查找列表中元素的组合

Finding combinations of elements in a list based on routing

我不确定如何口头表达我想要达到的目标,并为此制定一个适当的问题,所以这里有一个例子:

如果我有一个包含如下元素的综合列表:

list = ['A to B', 'B to C', 'C to D', 'D to E', 'A to C', 'A to D', 'A to E',
 'B to A', 'B to C', 'B to D', 'B to E', 'C to A', 'E to B', 'E to C', 'E to A']

我想找到表达路由的恰好 3 个元素的所有唯一组合,然后将这些组合存储在单独的列表中,如下所示:

['A to B', 'B to C', 'C to A'],

['B to C', 'C to A', 'A to B'],

etc.

因此,在第一个示例输出中,A 恢复为 A,在第二个输出中,B 恢复为 B。我希望看到任何事物以这种方式恢复为自身。

我是 Python 的新手,正在尝试想办法做到这一点,但我被卡住了。

我该如何实现?

也许使用 itertools 的排列可能不是最好的选择,但它会给出你想要的结果

#importing permutations from itertools
from itertools import permutations as c
lst= ['A to B', 'B to C', 'C to D', 'D to E', 'A to C', 'A to D', 'A to E',
 'B to A', 'B to C', 'B to D', 'B to E', 'C to A', 'E to B', 'E to C', 'E to A']
#permutation of the list with r as 3
lst_com = c(lst,3)
# this list is to reduce redundancy
d=[]
for i in lst_com:
    t=list(i)
    # if statement to check the express routing and not include redundant values
    if t[0][0] == t[2][-1] and t[0][-1] == t[1][0] and t[1][-1]==t[2][0] and t not in d:
        d.append(t)
        print(t)

输出:

['A to B', 'B to C', 'C to A']
['A to B', 'B to E', 'E to A']
['B to C', 'C to A', 'A to B']
['C to D', 'D to E', 'E to C']
['D to E', 'E to B', 'B to D']
['D to E', 'E to C', 'C to D']
['D to E', 'E to A', 'A to D']
['A to D', 'D to E', 'E to A']
['A to E', 'E to B', 'B to A']
['A to E', 'E to C', 'C to A']
['B to A', 'A to E', 'E to B']
['B to D', 'D to E', 'E to B']
['B to E', 'E to A', 'A to B']
['C to A', 'A to B', 'B to C']
['C to A', 'A to E', 'E to C']
['E to B', 'B to A', 'A to E']
['E to B', 'B to D', 'D to E']
['E to C', 'C to D', 'D to E']
['E to C', 'C to A', 'A to E']
['E to A', 'A to B', 'B to E']
['E to A', 'A to D', 'D to E']

我建议将所有步骤放入 key -> list of keys 的字典中。

你可以查询这个来得到所有的三胞胎:

data = ['A to B', 'B to C', 'C to D', 'D to E', 'A to C', 'A to D', 'A to E',
 'B to A', 'B to C', 'B to D', 'B to E', 'C to A', 'E to B', 'E to C', 'E to A']

from collections import defaultdict
routes = defaultdict(list)

for d in data:
    frm, to = d.split(" to ")
    routes[frm].append(to)

print (routes)

plets = set()

for frm, to in routes.items():
    for target in to:
        for target2 in routes[target]:
            if frm in routes[target2]: 
                plets.add( (frm, target, target2, frm) )

for t in sorted(plets):
    print(*t, sep= " -> ") 

输出:

defaultdict(<class 'list'>, {'A': ['B', 'C', 'D', 'E'], 
                             'B': ['C', 'A', 'C', 'D', 'E'], 
                             'C': ['D', 'A'], 
                             'D': ['E'], 
                             'E': ['B', 'C', 'A']})

A -> B -> C -> A
A -> B -> E -> A
A -> D -> E -> A
A -> E -> B -> A
A -> E -> C -> A
B -> A -> E -> B
B -> C -> A -> B
B -> D -> E -> B
B -> E -> A -> B
C -> A -> B -> C
C -> A -> E -> C
C -> D -> E -> C
D -> E -> A -> D
D -> E -> B -> D
D -> E -> C -> D
E -> A -> B -> E
E -> A -> D -> E
E -> B -> A -> E
E -> B -> D -> E
E -> C -> A -> E
E -> C -> D -> E

使用集合来存储您可能的路线可以避免多次获得相同的路线。


编辑输出问题:

def formIt(a,b,c,d):
    return f"{a} to {b}",f"{b} to {c}",f"{c} to {d}"

for frm, to in routes.items():
    for target in to:
        for target2 in routes[target]:
            if frm in routes[target2]: 
                plets.add( formIt(frm, target, target2, frm) )

for t in sorted(plets):
    print(*t, sep = ", ") 

得到

A to B, B to C, C to A 
A to B, B to E, E to A 
A to D, D to E, E to A 
 ... snipp...
E to C, C to A, A to E 
E to C, C to D, D to E