【问题标题】:Merge tuples in list with similar elements合并列表中具有相似元素的元组
【发布时间】:2018-02-03 18:37:27
【问题描述】:

我必须合并所有包含彼此至少一个元素的元组。

tups=[(1,2),(2,3),(8,9),(4,5),(15,12),(9,6),(7,8),(3,11),(1,15)]

第一个元组 (1,2) 应该与 (2,3),(3,11),(1,15),(15,12) 合并,因为这些元组中的每一个都包含前一个元组的相似项。所以最终的输出应该是

lst1 = [1,2,3,11,12,15]
lst2=[6,7,8,9] since (8,9),(9,6) and (7,8) have matching elements

到目前为止我的代码:

finlst=[]
for items in range(len(tups)):
    for resid in range(len(tups)):
        if(tups[items] != tups[resid] ):
            if(tups[items][0]==tups[resid][0] or tups[items][0]==tups[resid][1]):
                finlst.append(list(set(tups[items]+tups[resid])))

【问题讨论】:

  • 不清楚你在问什么。为什么(1,15) 应该与(3, 11) 合并? (1,15) 没有与(3, 15) 相同的元素,而(3,11) 没有与第一个元素(1, 2) 相同的元素。所以我想说这里的逻辑不清楚。您是在尝试将最后一场比赛作为下一场比赛的基础(例如(1,2) -> (2, 3) -> (3, 4)),还是将所有比赛都基于第一个元组(例如(1, 2) -> (2, 5) -> (6, 1))?

标签: python-3.x tuples


【解决方案1】:

我找到了解决方案,更多的是与连通性相关的图论问题,Connectivity-Graph Theory

我们可以为此使用 NetworkX,它几乎可以保证是正确的:

def uniqueGroup(groups):
#     grp=[]
#     for group in groups:
#         grp.append(list(group))
#     l=groups

    import networkx 
    from networkx.algorithms.components.connected import connected_components


    def to_graph(groups):
        G = networkx.Graph()
        for part in groups:
            # each sublist is a bunch of nodes
            G.add_nodes_from(part)
            # it also imlies a number of edges:
            G.add_edges_from(to_edges(part))
        return G

    def to_edges(groups):
        """ 
            treat `l` as a Graph and returns it's edges 
            to_edges(['a','b','c','d']) -> [(a,b), (b,c),(c,d)]
        """
        it = iter(groups)
        last = next(it)

        for current in it:
            yield last, current
            last = current    

    G = to_graph(groups)
    return connected_components(G)

输出:

tups = [(1, 2),(3,4),(1,4)]
uniqueGroup(tups)

{1, 2, 3, 4}

【讨论】:

    【解决方案2】:

    您可以这样做,使用通过匹配元组扩展的集合:

    tups = [(1, 2), (2, 3), (8, 9), (4, 5), (15, 12), (9, 6), (7, 8), (3, 11), (1, 15)]
    
    groups = []
    for t in tups:
        for group in groups:
            # find a group that has at least one element in common with the tuple
            if any(x in group for x in t):
                # extend the group with the items from the tuple
                group.update(t)
                # break from the group-loop as we don’t need to search any further
                break
        else:
            # otherwise (if the group-loop ended without being cancelled with `break`)
            # create a new group from the tuple
            groups.append(set(t))
    
    
    # output
    for group in groups:
        print(group)
    
    {1, 2, 3, 11, 15}
    {8, 9, 6, 7}
    {4, 5}
    {12, 15}
    

    由于此解决方案按顺序迭代原始元组列表一次,因此这不适用于连接不直接可见的输入。为此,我们可以改用以下解决方案,只要它仍然有效,就使用 fixed-point iteration 组合组:

    tups = [(1, 2), (3, 4), (1, 4)]
    
    import itertools
    
    groups = [set(t) for t in tups]
    while True:
        for a, b in itertools.combinations(groups, 2):
            # if the groups can be merged
            if len(a & b):
                # construct new groups list
                groups = [g for g in groups if g != a and g != b]
                groups.append(a | b)
    
                # break the for loop and restart
                break
        else:
            # the for loop ended naturally, so no overlapping groups were found
            break
    

    【讨论】:

    • 当 tups 列表为 tups = [(1, 2),(3,4),(1,4)] 时失败,预期输出为 {1,2,3,4} , 但是你的代码返回 {1, 2, 4}, {3, 4}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 2019-02-24
    • 2021-06-15
    相关资源
    最近更新 更多