代码之家  ›  专栏  ›  技术社区  ›  Nick Stinemates

是否有一种算法可以找到两个列表的唯一组合?5张名单?

  •  1
  • Nick Stinemates  · 技术社区  · 15 年前

    N 我希望找到的独特组合的列表。我已经把它写在我的白板上,这一切似乎都有一个模式,我只是还没有找到它。我觉得我可以表达一种暴力方法,这肯定是我追求的东西。还有别的选择吗?不同的数据结构(二叉树)会使这样的工作更合适吗?

    :

    #    1  2
    a = [1, 2]
    b = [a, b]
    

    结果将是:

    c = [1a, 1b, 2a, 2b] # (4 unique combinations)
    

    鉴于 :

    v = [1, a]
    w = [1, b]
    x = [1, c]
    y = [1, d]
    z = [1, e]
    

    结果将是:

    r = [11111, 1bcde, 11cde, 111de, 1111e, a1111, ab111, abc11, abcd1, abcde, 1b1d1, 1bc1e, 11c11, 11c1e, ... ] 
    
    7 回复  |  直到 15 年前
        1
  •  8
  •   unutbu    15 年前

    #!/usr/bin/env python
    import itertools
    a=[1,2]
    b=['a','b']
    c=[str(s)+str(t) for s,t in itertools.product(a,b)]
    print(c)
    ['1a', '1b', '2a', '2b']
    
    v=[1,'a']
    w=[1,'b']
    x=[1,'c']
    y=[1,'d']
    z=[1,'e']
    
    r=[''.join([str(elt) for elt in p]) for p in itertools.product(v,w,x,y,z)]
    print(r)
    # ['11111', '1111e', '111d1', '111de', '11c11', '11c1e', '11cd1', '11cde', '1b111', '1b11e', '1b1d1', '1b1de', '1bc11', '1bc1e', '1bcd1', '1bcde', 'a1111', 'a111e', 'a11d1', 'a11de', 'a1c11', 'a1c1e', 'a1cd1', 'a1cde', 'ab111', 'ab11e', 'ab1d1', 'ab1de', 'abc11', 'abc1e', 'abcd1', 'abcde']
    

    注意,产品产生2**5个元素。这是你想要的吗?

    itertools.product在Python 2.6中。对于以前的版本,您可以使用以下选项:

    def product(*args, **kwds):
            '''
            Source: http://docs.python.org/library/itertools.html#itertools.product
            '''
            # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
            # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
            pools = map(tuple, args) * kwds.get('repeat', 1)
            result = [[]]
            for pool in pools:
                result = [x+[y] for x in result for y in pool]
            for prod in result:
                yield tuple(prod)
    

    a b , v , w , x , y z 包含重复的元素。如果这是您的问题,那么您可以在将每个列表发送到itertools.product之前将其转换为一个集合:

    r=[''.join([str(elt) for elt in p]) for p in itertools.product(*(set(elt) for elt in (v,w,x,y,z)))]
    
        2
  •  2
  •   Jason Orendorff Oliver    15 年前

    对此,我认为另一个答案是:

    那里

    假设您只有两个列表要合并。通过制作网格,可以找到所有组合。

           black        blue
         +------------+------------+
    coat | black coat | blue coat  |
         +------------+------------+
    hat  | black hat  | blue hat   |
         +------------+------------+
    

    如您所见,有2*2个组合。如果有30种颜色和14种衣服,你会有30*14=420种组合。

    当您添加更多列表时,该模式将继续。您得到的不是二维矩形,而是三维长方体数组,或者最终是一个矩形 N

    如果知道有多少个列表,嵌套循环是生成所有组合的自然方式。

    for color in colors:
        for kind in kinds:
            print color, kind  # "black coat", "black hat", etc.
    

    如果列表以字典顺序开始,并且没有重复项,则输出也将以字典顺序进行。

        3
  •  2
  •   user229044    13 年前

    我不认为这个问题要求输入的功率集,我认为它要求输入集的笛卡尔积(部分)。如果我错了,我希望有人会纠正我。

    至于算法,现在你知道你在寻找什么了,谷歌将是你的朋友。

        4
  •  1
  •   Mark Byers    15 年前

    我假设您想要笛卡尔积——所有可能的列表都是通过从每个列表中选择一个元素创建的。您可以递归地实现它,如下所示:

    def cartesian_product(l):
        if l:
            for b in cartesian_product(l[1:]):
                for a in l[0]:
                    yield [a] + b
        else:
            yield []        
    
    l = [
     [ 'a', 'b' ],
     [ 'c', 'd', 'e' ],
     [ 'f', 'g' ],
    ]
    
    for x in cartesian_product(l):
        print x
    

    更新:~unutbu对itertools.product的建议更好,但我还是把它留在这里。

        5
  •  1
  •   mjv    15 年前

    因为你需要一个 笛卡尔积 ,使用 itertools

    >>> import itertools
    >>> v = [1, 'a']
    >>> w = [1, 'b']
    >>> x = [1, 'c']
    >>> y = [1, 'd']
    >>> z = [1, 'e']
    
    >>> p = [''.join(str(x) for x in c) for c in itertools.product(v,w,x,y,z)]
    >>> p
    ['11111', '1111e', '111d1', '111de', '11c11', '11c1e', '11cd1', '11cde', '1b111'
    , '1b11e', '1b1d1', '1b1de', '1bc11', '1bc1e', '1bcd1', '1bcde', 'a1111', 'a111e
    ', 'a11d1', 'a11de', 'a1c11', 'a1c1e', 'a1cd1', 'a1cde', 'ab111', 'ab11e', 'ab1d
    1', 'ab1de', 'abc11', 'abc1e', 'abcd1', 'abcde']
    >>>
    
        6
  •  1
  •   Johannes Charra    15 年前

    def getAllCombinations(listOfLists):
        if len(listOfLists) == 1:
            return [str(x) for x in listOfLists[0]]
    
        result = set()
        head, tail = listOfLists[0], listOfLists[1:]
    
        tailCombs = getAllCombinations(tail)
        for elem in head:
            for tc in tailCombs:
                result.add(str(elem) + tc)
        return result
    
    v = [1, 'a']
    w = [1, 'b']
    x = [1, 'c']
    y = [1, 'd']
    z = [1, 'e']
    
    >>> print getAllCombinations([v, w, x, y, z])
    set(['111de', 'abc11', 'a1c1e', 'a111e', '11c11', 'ab11e', '1bc11', 'ab1d1', 'a1cd1', '1b1de', 'a11d1', '11111', '1b111', '11cd1', 'abcd1', '1bcde', 'ab111', '1bc1e', 'abc1e', '111d1', 'a1111', '11c1e', 'a1c11', '11cde', '1b11e', '1bcd1', 'abcde', 'a1cde', '1b1d1', 'a11de', 'ab1de', '1111e'])
    
        7
  •  0
  •   Jason Orendorff Oliver    15 年前

    c = [(x, y) for x in a for y in b]
    r = [(vv, ww, xx, yy, zz)
         for vv in v  for ww in w  for xx in x  for yy in y  for zz in z]