【问题标题】:Cartesian product of different size不同大小的笛卡尔积
【发布时间】:2014-04-08 22:13:05
【问题描述】:

感谢itertools.product() 函数,我可以得到列表的笛卡尔积:

lists = [['A', 'B'], ['1', '2'], ['x', 'y']]
combinations = itertools.product(*lists)
# [('A', '1', 'x'), ('A', '2', 'y'), ..., ('B', '2', 'y')]

我想要的是相同的东西,但尺寸不同:

all_comb = magicfunction(lists)
# [('A', '1', 'x'), ..., ('B', '2', 'y'), ('A', '1'), ('A', '2'), ... ('2', 'y'), ... ('y')]

我看不出一种明显的方法。

我需要一种可以让我设置元组的最小和最大大小的方法(我处理长列表并且只需要从 7 到 3 的大小组合,列表的数量和它们的大小会有所不同)。

我的列表更像:

lists = [['A', 'B', 'C'], ['1', '2'], ['x', 'y', 'z', 'u'], ...] # size may go to a few dozens

【问题讨论】:

    标签: python list itertools cartesian-product


    【解决方案1】:

    只需根据较小尺寸的组合将多个产品链接在一起:

    from itertools import chain, product, combinations
    
    def ranged_product(*lists, **start_stop):
        start, stop = start_stop.get('start', len(lists)), start_stop.get('stop', 0)
        return chain.from_iterable(product(*comb)
                                   for size in xrange(start, stop - 1, -1)
                                   for comb in combinations(lists, r=size))
    

    演示:

    >>> lists = [['A', 'B'], ['1', '2'], ['x', 'y']]
    >>> for prod in ranged_product(stop=2, *lists):
    ...     print prod
    ... 
    ('A', '1', 'x')
    ('A', '1', 'y')
    ('A', '2', 'x')
    ('A', '2', 'y')
    ('B', '1', 'x')
    ('B', '1', 'y')
    ('B', '2', 'x')
    ('B', '2', 'y')
    ('A', '1')
    ('A', '2')
    ('B', '1')
    ('B', '2')
    ('A', 'x')
    ('A', 'y')
    ('B', 'x')
    ('B', 'y')
    ('1', 'x')
    ('1', 'y')
    ('2', 'x')
    ('2', 'y')
    

    【讨论】:

    • 虽然我发现您处理启动/停止的方式有些奇怪,但您的回答基本上得出了相同的结论:“使用组合的第二个参数”。您的答案提供了一个功能,可以轻松设置最小值和最大值。但是,我不需要根据我的数据设置不同的 min/max 值,并且可以通过在调用范围中使用 min(maxsize, len(lists)) 来限制它来解决这个问题。谢谢你的回答和演示:)
    • @sildar:startstop 的处理基于range() 的处理方式,但在这种情况下可能有点过于复杂。我会简化的。
    【解决方案2】:
    >>> from itertools import product, combinations
    >>> lists = [['A', 'B'], ['1', '2'], ['x', 'y']]
    >>> for i in xrange(2, len(lists)+1):
        for c in combinations(lists, i):
            print list(product(*c))
    ...         
    [('A', '1'), ('A', '2'), ('B', '1'), ('B', '2')]
    [('A', 'x'), ('A', 'y'), ('B', 'x'), ('B', 'y')]
    [('1', 'x'), ('1', 'y'), ('2', 'x'), ('2', 'y')]
    [('A', '1', 'x'), ('A', '1', 'y'), ('A', '2', 'x'), ('A', '2', 'y'), ('B', '1', 'x'), ('B', '1', 'y'), ('B', '2', 'x'), ('B', '2', 'y')]
    

    【讨论】:

    • 我误解了 combinaisons() 的第二个参数的目的,因为文档在其示例中使用字符串作为可迭代对象。有一种明显的方法可以做到这一点。谢谢。我想我可以通过限制范围来设置最大尺寸。
    猜你喜欢
    • 2019-04-29
    • 2020-07-05
    • 2017-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    相关资源
    最近更新 更多