2016-09-17 3 views
1

나는처럼 보이는 파이썬 목록을 가지고있다. 값의 순서는 중요하지 않으므로 1,2는 2,1과 같습니다. 또한 각 조합에 포함되지 않은 값이 포함 된 다른 목록을 반환하고자합니다. 예를 들어 다음에 대한파이썬 조합한다고 가정

Combination 1,2/Remainder 3,4 
Combination 2,3/Remainder 1,4 
Combination 1,2,3/Remainder 4 
Combination 1,2,3,4/ Remainder - 

반환 목록은 위의 내가 첫 번째 부분은 아마 달성 할 수 있다는 걸 난 단지 몇 가지 예를 보여 주었다

combination = [[1,2], [2,3], [1,2,3], [1,2,3,4]] 
remainder = [[3,4], [1,4], [4], []] 

...

itertools.combinations을 사용하지만 루프없이 조합에 사용되지 않은 값을 어떻게 반환 할 수 있습니까?

답변

2

건물, 대신 이진 특정 범위의 숫자를 변환, 당신은 단지 모든 조합을 얻을 수 itertools.product을 사용할 수 있습니다 및 0 (또는 TrueFalse)을 입력 한 다음이를 "ins"및 "outs"을 필터링하기위한 마스크로 사용하십시오.

>>> lst = [1,2,3] 
>>> products = list(product([1,0], repeat=len(lst))) 
>>> [[lst[i] for i, e in enumerate(p) if e] for p in products] 
[[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []] 
>>> [[lst[i] for i, e in enumerate(p) if not e] for p in products] 
[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]] 

또한 그 enumerate 이해하는 기능을 정의하고 한 번에 두 부분을 할 수있는 : 목록 "에서", 당신이 할 수에서

>>> mask = lambda lst, p, v: [lst[i] for i, e in enumerate(p) if e == v] 
>>> [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0], repeat=len(lst))] 
[([1, 2, 3], []), 
([1, 2], [3]), 
([1, 3], [2]), 
([1], [2, 3]), 
([2, 3], [1]), 
([2], [1, 3]), 
([3], [1, 2]), 
([], [1, 2, 3])] 

만 2 개 이상으로 조합을 원하는 경우 조건 추가 :

>>> [(mask(lst, p, 1), mask(lst, p, 0)) for p in product([1,0],repeat=len(lst)) if sum(p) >= 2] 

또는 numpy 배열을 사용하고 numpy의 고급 색인을 사용합니다

>>> arr = np.array([1,2,3]) 
>>> [(arr[p==1], arr[p==0]) for p in map(np.array, product([1,0], repeat=len(arr)))] 
[(array([1, 2, 3]), array([])), 
(array([1, 2]), array([3])), 
(array([1, 3]), array([2])), 
(array([1]), array([2, 3])), 
(array([2, 3]), array([1])), 
(array([2]), array([1, 3])), 
(array([3]), array([1, 2])), 
(array([]), array([1, 2, 3]))] 
+0

정말 멋진 구현 !!! –

+0

이 솔루션을 좋아합니다! 꿈처럼 작동합니다! 고맙습니다 – Mark

2

당신은 차이 집합으로 수행 할 수 있습니다

l = set([1, 2, 3, 4]) 

for i in range(len(l)+1): 
    for comb in itertools.combinations(l, i): 
     print(comb, l.difference(comb)) 

() {1, 2, 3, 4} 
(1,) {2, 3, 4} 
(2,) {1, 3, 4} 
(3,) {1, 2, 4} 
(4,) {1, 2, 3} 
(1, 2) {3, 4} 
(1, 3) {2, 4} 
(1, 4) {2, 3} 
(2, 3) {1, 4} 
(2, 4) {1, 3} 
(3, 4) {1, 2} 
(1, 2, 3) {4} 
(1, 2, 4) {3} 
(1, 3, 4) {2} 
(2, 3, 4) {1} 
(1, 2, 3, 4) set() 
+0

집합 차이는 목록에 중복이없는 경우에만 작동합니다. –

1

는이 벡터가 있다고 가정을 [1 6 3] 당신은 3입니다 0 3-1^2에서 모든 숫자를 생성 할 수 있습니다

len([1 6 3])

0 
1 
2 
3 
4 
5 
6 
7 

2 진에이 숫자를 변환 할 수 있습니다 후 :

0 0 0 
0 0 1 
0 1 0 
0 1 1 
1 0 0 
1 0 1 
1 1 0 
1 1 1 
01 조합의 1의 같은 위치에와의 위치에 하나 그 나머지에있는 번호를 추가

[1 6 3] 
0 0 0 
0 0 1 
0 1 0 
0 1 1 
1 0 0 
1 0 1 
1 1 0 
1 1 1 

각 라인 : 23,516,

생성 순서의 상단에 벡터를 넣어 0.

때문에, 예를 들어, 4 번째 줄에서 찾고 :

Combination: [6,3] 
Remainder: [1] 

끝에 : 여기

Combination: [],[3],[6],[6,3],[1],[1,3],[1,6],[1,6,3] 
Remainder: [1,6,3],[1,3],[1],[6,3],[6],[3],[] 

코드 :

vec=[1,3,6] 
binary_vec = [format(i,'b').zfill(len(vec)) for i in range(2**len(vec))] 
print([[vec[i] for i,y in enumerate(x) if y != "0"] for x in binary_vec]) 
print([[vec[i] for i,y in enumerate(x) if y == "0"] for x in binary_vec]) 

출력 :

enter image description here 이 게시물에 내 대답에도

봐 : Nunzio에 의해 아이디어에 따라

Determine list of all possible products from a list of integers in Python

+0

흥미로운 접근 방법. 당신은 또한 그것을위한 약간의 코드를 제공 할 수 있습니까? 또한 바이너리로 변환하는 대신 itertools.product ([True, False], repeat = 3)를 사용할 수 있습니다. –

+0

@tobias_k 감사합니다! 나는이 함수를 모른다 : itertools.product ([True, False], repeat = 3)! 나는 또한 코드를 제공했다. –