2012-03-25 3 views
1

다음과 같은 복잡한 문제를 단순화하고 있습니다 ...배열 집합의 요소 조합을 모두 찾는 방법은 무엇입니까?

세 개의 정수 배열을 가정 할 때 각 요소의 가능한 모든 조합을 반환하는 가장 효율적인 방법은 무엇입니까? 각 배열의 각 값은 항상 동일한 위치에 지정되므로 [A,B,C][C,B,A]과 같을 것입니다. 원하는 결과는 각 해시가 단일 조합을 포함하는 배열의 배열입니다. 예를 들어 :

을 감안할 때 :

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

이 결과는 다음과 같습니다

itertools.product(array1, array2, array3) 

을하고 필요한 경우 list에 포장 :

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

왜 3 가지 다른 언어로 질문이 있습니까? – Amber

+0

재귀가 가장 간단한 해결책이라고 생각합니다. – kirilloid

+0

단지 for-loops가 아닌가? – Pinch

답변

8

파이썬에서, itertools.product를 사용 반복 가능하지 않은 시퀀스. 코드의 버전은 특히 효율적이지 않지만

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) 

:

당신이 어떻게하는지보고 싶다면

이는 itertools 문서에 나와있는 "해당"코드입니다.

PyPy version of itertools에는 파이썬 구현도 있습니다.

3

여기 파이썬에서 그 일의 다소 자세한 방법 :

# 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 
+1

이것은 확장되지 않습니다. 반복 가능한 반복 수에 따라 다른 버전을 써야합니다. – agf

+2

그래, 그냥 원리를 보여. 귀하의 답변은 훨씬 뛰어나지 만 코드 작성을 배우는 사람에게는 이해하기 어렵습니다. –

+0

표준 라이브러리 함수를 호출하는 것이 "이해하기 어렵습니다"? –

4

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')] 
+0

그건 내 대답의 첫 부분입니다. – agf

+3

FWIW, 내 대답은 독립적으로 구성되었으며 OP의 데이터를 사용하여 해결 된 예를 보여줍니다. * itertools *와 그 문서의 저자로서 나는 다른 대답을 줄 것을 기대하지 않는다 :-) –

3

자바 스크립트의 솔루션입니다
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"] 
*/ 

모든 수의 어레이에서 작동합니다.

데모 :

+0

매개 변수의 위치를 ​​기록하면 출력에 매개 변수의 값을 기록하는 대신 원래의 o (n)리스트에서 이것은 일련의 위치가됩니다. 이 시퀀스가 ​​무엇인지 아는 사람 있습니까? – varun

1

http://jsfiddle.net/u9zJQ/는 @의 stewe의 대답의 파이썬 equivalant했다. 나는이 대답이 더 좋고 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 
관련 문제