【问题标题】:Finding combinations of elements in a list based on routing基于路由查找列表中元素的组合
【发布时间】:2020-05-30 10:57:42
【问题描述】:

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

如果我有一个包含以下元素的完整列表:

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 新手,我正在想办法做到这一点,但我卡住了。

我将如何实现这一目标?

【问题讨论】:

    标签: python-3.x list pattern-matching


    【解决方案1】:

    也许使用来自 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']
    

    【讨论】:

    • 谢谢!但是,我的列表中有 810 个元素。出现内存错误。有没有办法在置换函数期间评估条件,只存储必要的?或者另一种优雅的方式来避免遇到内存问题?
    • 你会提供清单吗?
    • 我已经完成了,将数据集拆分成逻辑上更小的部分。
    【解决方案2】:

    我建议将所有步骤放入它导致的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 
    

    【讨论】:

    • 我喜欢这个解决方案,但我需要明确地将其保持为“A 到 B”、“B 到 C”等。我会看看我是否仍然可以应用此代码,因为从直觉上看,使用字典似乎可以解决我从 TonyStark 的解决方案中得到的内存错误。
    • @Mighty 您可以从数据中重新创建输入 - 请参阅编辑。 ...并再次编辑。
    猜你喜欢
    • 1970-01-01
    • 2012-04-11
    • 2021-03-10
    • 2018-01-15
    • 2011-01-12
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 2018-09-20
    相关资源
    最近更新 更多