【问题标题】:How can I find all the combinations of elements in a set of arrays? [duplicate]如何找到一组数组中的所有元素组合? [复制]
【发布时间】:2012-04-09 02:23:29
【问题描述】:

我正在用以下方法简化一个更大的复杂问题...

给定三个整数数组,返回每个元素的所有可能组合的最有效方法是什么?请注意,每个数组中的每个值都将始终在相同的位置给出,因此[A,B,C] 将与[C,B,A] 相同。我想要的结果是一个数组数组,每个哈希包含一个组合。例如:

给定:

var array1 = [1,2]
var array2 = [a,b]
var array3 = [foo,bar]

结果是:

[
  [1,a,foo],
  [2,a,foo],
  [1,b,foo],
  [2,b,foo],
  [1,a,bar],
  [2,a,bar],
  [1,b,bar],
  [2,b,bar]
]

【问题讨论】:

  • 为什么您的问题中标记了 3 种不同的语言?
  • 我想,递归将是最简单的解决方案。
  • 我标记了 3 种不同的语言,因为我很乐意看到其中任何一种语言的解决方案。
  • @stewe 感谢您这样做。

标签: python algorithm


【解决方案1】:

在 Python 中,使用 itertools.product:

itertools.product(array1, array2, array3)

如果您需要一个序列,而不仅仅是一个可迭代对象,请将其包装在 list 中。

如果您想看看它是如何完成的,这是itertools 文档中给出的“等效”代码:

def product(*args, **kwds):
    # 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)

虽然那个版本的代码不是特别高效。

PyPy version of itertools 中还有一个 Python 实现。

【讨论】:

    【解决方案2】:

    itertools.product直接解决了这个问题,速度非常快:

    >>> from itertools import product
    >>> list(product([1,2], ['a', 'b'], ['foo', 'bar']))
    [(1, 'a', 'foo'), (1, 'a', 'bar'), (1, 'b', 'foo'), (1, 'b', 'bar'), (2, 'a', 'foo'), (2, 'a', 'bar'), (2, 'b', 'foo'), (2, 'b', 'bar')]
    

    【讨论】:

    • 这是我回答的第一部分。
    • FWIW,我的答案是独立构建的,它显示了一个使用 OP 数据的已解决示例。作为 itertools 及其文档的作者,我认为您不会期望我给出任何其他答案 :-)
    【解决方案3】:

    这是在 Python 中执行此操作的一种相当冗长的方法:

    # define the sets of items
    array1 = [1,2]
    array2 = ['a', 'b']
    array3 = ['foo', 'bar']
    
    # create an empty list to collect combinations
    all_combinations = []
    
    # enumerate all combinations by nested iteration
    for i in array1:
        for j in array2:
            for k in array3:
                all_combinations.append([i, j, k]) 
    
    # print all combinations
    for item in all_combinations:
        print item
    

    【讨论】:

    • 这无法扩展——您必须为每个不同数量的可迭代对象编写不同的版本。
    • 是的,只是演示原理。您的答案要好得多,但对于任何学习编码的人来说也不太容易理解。
    • 调用标准库函数是“难以理解”?
    • 如果目标是了解某些东西是如何工作的,我认为黑匣子无济于事。如果您是 Python 新手或一般编程新手,查看 itertools.product 的源代码(或等效源代码)可能会让事情变得更糟。
    • 我大体上同意你的观点,但是你的代码太简单了——不足以说明如何解决问题。你没有展示了这个原则。能够处理任意数量的迭代是问题的核心。问题没那么简单。
    【解决方案4】:

    这里是 javascript 中的解决方案:

    function p(o){
        var count=1;
        var step_len=[];
        for(var i=0;i<o.length;i++){
            step_len[i]=count;
            count*=o[i].length;
        }
        for(var i=0;i<count;i++){
            var tmp=[];
            for(var n=0;n<o.length;n++){
                tmp.push(o[n][Math.floor(i/step_len[n])%o[n].length]);
            }
            console.log(tmp);
        }
    }
    
    var o=[
        [1,2],
        ['a','b'],
        ['foo','bar']
    ];
    
    p(o);
    
    /* console output:
    [1, "a", "foo"]
    [2, "a", "foo"]
    [1, "b", "foo"]
    [2, "b", "foo"]
    [1, "a", "bar"]
    [2, "a", "bar"]
    [1, "b", "bar"]
    [2, "b", "bar"]
    */
    

    它适用于任意数量的数组。

    演示:http://jsfiddle.net/u9zJQ/

    【讨论】:

    • 如果不是在输出中记录参数的值,而是在原始 o(n) 列表中记录参数的位置,这将是一个位置序列。有人知道这个序列叫什么吗?
    【解决方案5】:

    刚刚做了一个与@stewe 的答案等效的python。我更喜欢这个答案,而不是任何带有 itertools 的答案,因为它更通用,可以应用于任何语言。我在 VBA 中需要它,它就像一个魅力.. +1

    def p(o):
        count=1
        step_len=[]
        for i, item in enumerate(o):
            step_len.append(count)
            count *= len(o[i])
    
        for i in range(count):
            tmp=[]
            for n, item in enumerate(o):
                tmp.append(o[n][(i//step_len[n]) % len(o[n])])
    
            print tmp
        print count
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-05
      • 2013-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多