组合列表列表中至少有一个共同数字的列表,Python

组合列表列表中至少有一个共同数字的列表,Python,python,list,Python,List,考虑以下列表: l = [ [1], [1], [1,2,3], [4,1], [5], [5], [6], [7,8,9], [7,6], [8,5] ] 我想合并所有至少有一个共同数字的列表,这将以迭代的方式进行,直到完成为止,并且不会出现任何重复字母。结果将是: combine(l) = [ [1,2,3,4], [5,6,7,8,9] ] 有没有什么好方法可以做到这一点,也许是用itertools out = [] for l in lists: for o in out:

考虑以下列表:

l = [ [1], [1], [1,2,3], [4,1], [5], [5], [6], [7,8,9], [7,6], [8,5] ]
我想合并所有至少有一个共同数字的列表,这将以迭代的方式进行,直到完成为止,并且不会出现任何重复字母。结果将是:

combine(l) = [ [1,2,3,4], [5,6,7,8,9] ]
有没有什么好方法可以做到这一点,也许是用itertools

out = []
for l in lists:
    for o in out:
        if set(l).intersection(set(o)):
            o[:] = list(set(l) + set(o))  # Mutate, don't reassign temp var
            break
    else:
        out.append(l)
写得不完美,可以优化,也没有排序,但应该能让你知道怎么做。

也许是这样

l = [ [1], [1], [1,2,3], [4,1], [5], [5], [6], [7,8,9], [7,6], [8,5] ]
a, b = [], map(set, l)

while len(a) != len(b):
    a, b = b, []
    for x in a:
        for i, p in enumerate(b):
            if p & x:
                b[i] = p | x
                break
        else:
            b.append(x)        

print a
# [set([1, 2, 3, 4]), set([5, 6, 7, 8, 9])]
我天真的尝试:

  • 当元组的交集不为空时合并所有元组
  • 对每个元组排序
  • 删除重复元组
  • 重复此操作,直到不再有任何更改

  • 例如:

    def combine_helper(l):
        l = map(set, l)
        for i, x in enumerate(l, 1):
            x = set(x)
            for y in l[i:]:
                if x & y:
                    x = x | y
            yield tuple(sorted(x))
    
    def combine(l):
        last_l = []
        new_l = l
        while last_l != new_l:
            last_l = new_l
            new_l = list(set(combine_helper(last_l)))
        return map(list, last_l)
    
    l = [ [1], [1], [1,2,3], [4,1], [5], [5], [6], [7,8,9], [7,6], [8,5] ]
    print combine(l)
    
    >>> compose(l)
    [set([1, 2, 3, 4]), set([8, 9, 5, 6, 7])]
    
    输出:

    $ python test.py
    [[1, 2, 3, 4], [5, 6, 7, 8, 9]]
    

    回归拯救!别忘了减少

    input_list = [ [1], [1], [1, 2, 3], [4, 1], [5], [5], [6], [7, 8, 9], 
                   [7, 6], [8, 5] ]
    def combine(input_list):
        input_list = map(set, input_list) # working with sets has some advantages
        reduced_list = reduce(combine_reduce, input_list, [])
        if len(reduced_list) == len(input_list):
            # return the whole thing in the original format (sorted lists)
            return map(sorted, map(list, reduced_list))
        else:
            # recursion happens here
            return combine(reduced_list)
    
    def combine_reduce(reduced_list, numbers):
        '''
        find the set to add the numbers to or append as a new set.
        '''
        for sub_set in reduced_list:
            if sub_set.intersection(numbers):
                sub_set.update(numbers)
                return reduced_list
        reduced_list.append(numbers)
        return reduced_list
    
    print combine(input_list)
    
    打印出:

    $ python combine.py
    [[1, 2, 3, 4], [5, 6, 7, 8, 9]]
    
    我们这里有两件事。第一个是
    reduce
    :我正在使用它来制作列表,将每个元素装配到结果列表的某个位置,或者在不起作用的情况下附加它。但是,这并不能完成全部工作,所以我们重复这个过程(递归!),直到reduce不能提供更短的列表


    此外,使用
    set
    可以使用方便的
    intersection
    方法。您会注意到带有
    map(set,input\u list)
    的行在递归中是多余的。从内部函数
    combine\u internal
    提取包装函数
    combine
    ,并将格式化/反格式化(从
    list
    set
    并返回)放在外部函数中,这是一个练习。

    可以引入以下尝试:

  • 创建一个单元素集列表,列表中包含各个值。这是输出列表
  • l列表是一个配方,说明了输出列表中的项目应该如何连接。e、 g.如果输出列表是
    [{1},{2},{3}]
    ,并且l列表中的第一个元素是
    [1,3]
    ,那么输出列表中包含1和3的所有集合都应该合并:
    输出=[{1,3},{2}]
  • 重复步骤2。对于l列表上的每个项目
  • 代码:

    例如:

    def combine_helper(l):
        l = map(set, l)
        for i, x in enumerate(l, 1):
            x = set(x)
            for y in l[i:]:
                if x & y:
                    x = x | y
            yield tuple(sorted(x))
    
    def combine(l):
        last_l = []
        new_l = l
        while last_l != new_l:
            last_l = new_l
            new_l = list(set(combine_helper(last_l)))
        return map(list, last_l)
    
    l = [ [1], [1], [1,2,3], [4,1], [5], [5], [6], [7,8,9], [7,6], [8,5] ]
    print combine(l)
    
    >>> compose(l)
    [set([1, 2, 3, 4]), set([8, 9, 5, 6, 7])]
    

    但是你会将最后一个列表添加到第一个列表(5个公共列表)还是第二个列表(8个公共列表)?抱歉写错了。你的意思是
    combine(l)=[[1,2,3,4],[5,8],[6,7],[6,7,8,9]
    ?嗯,我希望它是迭代完成的,所以完成的结果将与示例中的一样。如果我理解正确,这称为(或者,您可以将其视为连接组件问题)。请参阅许多实现。也许我遗漏了一些内容,但由于
    out
    开始时是空的,因此我看不到
    for o in out
    下的任何代码是如何运行的。如果设置了
    (l)。交叉点(设置(o)):