-
[파이썬] from itertoolsPython/파이썬 자료구조 알고리듬 2021. 11. 8. 14:09반응형
파이썬의 이터툴즈 중 조합형 이터레이터에 대해 알아보겠습니다.
조합형 이터레이터는 다음 4가지가 있습니다.
product(),
permutations(),
combinations(),
combinations_with_replacement()가장 익숙한 순열부터 보도록 하죠.
permutations(순열)
고등학교 교육과정에서 배운 개념.
'순'열에는 '순'서가 있습니다.from itertools import permutations print(tuple(permutations((1, 2, 3)))) # ((1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1))
3가지 원소를 1열로 세운다면...
모든 경우의 수는 3! 이죠. 3 * 2 * 13가지 원소중 2개만 뽑아 1열로 세운다면..
모든 경우의 수는 3 * 2입니다.print(tuple(permutations((1, 2, 3), 2))) # ((1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2))
combinations(조합)
마찬가지로 고등학교 교육과정에 있는 내용이죠.
from itertools import combinations print(tuple(combinations((1, 2, 3)))) # TypeError: combinations() missing required argument 'r' (pos 2)
두 번째 인자를 입력하지 않으면 에러가 나옵니다.
조합에는 순서가 없습니다.
3 종류 원소가 있을 때 순서 없이 (=순서를 무시하고) 3개를 뽑을 때 모든 경우의 수는 1입니다.print(tuple(combinations((1, 2, 3), 3))) # ((1, 2, 3),)
그래서 두 번째 인자가 없으면 에러가 발생하도록 만들었나 봅니다.
3가지 요소 중 순서 없이 2개를 뽑는 모든 경우의 수
print(tuple(combinations((1, 2, 3), 2))) # ((1, 2), (1, 3), (2, 3))
정상적으로 사용하면 이런 결과가 나옵니다.
n! / (r! * (n-r)!)product
from itertools import product print(tuple(product((1, 2, 3)))) # ((1,), (2,), (3,))
이건 뭘까요?
다중 for문을 연상하면 됩니다.
print(tuple(product((1, 2, 3), ('a', 'b')))) # ((1, 'a'), (1, 'b'), (2, 'a'), (2, 'b'), (3, 'a'), (3, 'b')) for num in (1, 2, 3): for letter in ('a', 'b'): print(num, letter) # 1 a # 1 b # 2 a # 2 b # 3 a # 3 b
이런 걸 데카르트 곱(cartesian product)이라고 합니다.
print(tuple(product((1, 2, 3), (1, 2, 3)))) # ((1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3))
product를 중복 순열이라고도 합니다.
from itertools import product print(tuple(product((0, 1, 2), (0, 1, 2), (0, 1, 2)))) print(tuple(product((0, 1, 2), repeat=3))) # 위와 같다. ((0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0), (0, 2, 1), (0, 2, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2))
combinations_with_replacement
from itertools import combinations_with_replacement print(tuple(combinations_with_replacement((1, 2, 3)))) # TypeError: combinations_with_replacement() missing required argument 'r' (pos 2)
에러가 나옵니다.
그럼 이렇게....
print(tuple(combinations_with_replacement((1, 2, 3), 2))) # ((1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3))
이 결과를 다음(프로덕트)과 비교해 보시면 뭔지 아실 수 있을 겁니다.
print(tuple(product((1, 2, 3), (1, 2, 3)))) # ((1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3), (3, 1), (3, 2), (3, 3))
둘을 비교해 보면
combinations_with_replacement는
순서가 없는 (순서를 무시한) 프로덕트란 것을 알 수 있습니다.중복조합이라고도 합니다.
프로덕트는 for문과 같다고 했습니다.
같은 배열로 여러 번 for를 돌렸을 때,
결과물의 순서가 없다면
이런 결과가 나오는 것이죠.왜 두 번째 인수가 필요한 지도
알 수 있습니다.------------------------------------------
어떤 그룹의 물건을 n회 뽑아서
가격표를 만들어야 할 때
'combinations_with_replacement'를
이용할 수 있습니다.다중 for 문을 이용하면 겹치는 경우가 많이 발생합니다.
group_a = dict(x=0, a=360, b=170, c=57) for key1, value1 in group_a.items(): for key2, value2 in group_a.items(): print(key1, key2, value1 + value2)
x x 0 x a 360 x b 170 x c 57 a x 360 a a 720 a b 530 a c 417 b x 170 b a 530 b b 340 b c 227 c x 57 c a 417 c b 227 c c 114
combinations_with_replacement를 이용하면,
연산 횟수가 16회에서 10회로 줍니다.from itertools import combinations_with_replacement group_a = dict(x=0, a=360, b=170, c=57) for (key1, value1), (key2, value2) in combinations_with_replacement(group_a.items(), 2): print(key1, key2, value1 + value2)
x x 0 x a 360 x b 170 x c 57 a a 720 a b 530 a c 417 b b 340 b c 227 c c 114
------------------------------------------
딕셔너리를
group_a = {'x': 0, 'a': 360, 'b': 170, 'c': 57}
이렇게 사용하는 게 일반적이지만,
작은따옴표의 압박이 있을 때는group_a = dict(x=0, a=360, b=170, c=57)
이것도 좋습니다.
반응형