代码之家  ›  专栏  ›  技术社区  ›  MikeRand

分组间无重复的组合/排列

  •  2
  • MikeRand  · 技术社区  · 16 年前

    function 1:
    
    list1 = [0,1,2] #any list of single-integer elements
    list2 = [0,3,4]
    list3 = [0,2,4]
    
    function1(list1, list2, list3)
    
    >>> (0,3,2),(0,3,4),(0,4,2),(1,0,2),(1,0,4),(1,3,0),(1,3,2),(1,3,4),
        (1,4,0),(1,4,2),(2,0,4),(2,3,0),(2,3,4),(2,4,0)
    

    基本上,它生成所有有效的排列,定义为a)每个列表中有一个元素,b)没有相同值的元素。

    function 2:
    
    list1 = [(0,1),(0,2),(0,3)] #any list of double-integer tuples
    list2 = [(0,4),(1,4),(2,4)]
    
    function2(list1, list2)
    >>> ((0,1),(2,4)) , ((0,2),(1,4)) , ((0,3),(1,4)) , ((0,3),(2,4))
    

    函数2生成任何排列,每个列表中有一个元组,并且每个元组中没有重复的元素。

    我查看了Python itertools帮助,没有找到任何复制这些伪函数的东西。有什么想法吗?

    谢谢,

    迈克

    5 回复  |  直到 16 年前
        1
  •  4
  •   Pär Wieslander    16 年前
    from itertools import product
    def function1(*seqs):
      return (x for x in product(*seqs) if len(x) == len(set(x)))
    
    >>> list(function1([0,1,2], [0,3,4], [0,2,4]))
    [(0, 3, 2), (0, 3, 4), (0, 4, 2), (1, 0, 2), (1, 0, 4), (1, 3, 0), (1, 3, 2), (1, 3, 4), (1, 4, 0), (1, 4, 2), (2, 0, 4), (2, 3, 0), (2, 3, 4), (2, 4, 0)]
    
        2
  •  3
  •   John La Rooy    16 年前

    P¤r Wieslander为函数1给出了一个很好的通用解决方案。下面是函数2的一般解决方案

    from itertools import product
    def function2(*args):
        return [i for i in product(*args) if (lambda x: len(x) == len(set(x)))([k for j in i for k in j])]
    

    当然,如果生成器表达式更符合您的目的,您可以返回它。
    例如:

    def function2(*args):
        return (i for i in product(*args) if (lambda x: len(x) == len(set(x)))([k for j in i for k in j]))
    
        3
  •  1
  •   Mad Scientist    16 年前
    >>> [(x,y,z) for x in list1 for y in list2 for z in list3 if (x != y and y != z
    and x != z)]
    [(0, 3, 2), (0, 3, 4), (0, 4, 2), (1, 0, 2), (1, 0, 4), (1, 3, 0), (1, 3, 2), (1
    , 3, 4), (1, 4, 0), (1, 4, 2), (2, 0, 4), (2, 3, 0), (2, 3, 4), (2, 4, 0)]
    

    对于第一个

        4
  •  1
  •   Mike Graham    16 年前
    def f2(first, second):
        for a in first:
            for b in second:
                if len(set(a + b)) == 4:
                    yield (a, b)
    
        5
  •  0
  •   MikeRand    16 年前

    对于任何想知道的人来说,这里是最终的实现:

    def function2(arg1, arg2):
        return [i for i in product(*arg1) if (lambda x: len(x) == len(set(x)))
                ([k for j in i for k in j] + arg2)]
    

    gnibbler卓越解决方案的两个变化:

    2) arg2是我要从任何组合中排除的内容的列表。将它们包含在lambda函数的参数中,可以进一步约束乘积(*arg1)的结果,而无需引入组合。

    使用命名变量向您展示我对其所做的操作,下面是确切的代码:

    def makeMyMenu(allmeals, dont_eat):
        return [menu for menu in product(*allmeals) if (lambda x: len(x) == len(set(x)))
                ([ingredient for meal in menu for ingredient in meal] + dont_eat)]