Python itertools

파이썬으로 코딩할 때, 종종 순열, 조합, product를 구현하거나 사용해야 할 때가 있다. 이럴 때 힘들게 구현하지 말고 파이썬에서 만들어둔 표준 라이브러리인 itertools를 사용해보자

combinations

조합을 표현할 때 사용되는 메소드이다. 한 리스트에서 중복을 허용하지 않고 모든 경우의 수를 구하는 것이다. 반환되는 항목의 수는 n! / r! / (n - r)!이다. 사용법은 다음과 같다.

from itertools import combinations

_list = [1, 2, 3]
combi = list(combinations(_list, 2))
print(combi)														# [(1, 2), (1, 3), (2, 3)]
# 갯수 별로 조합을 반복할 수 있다.
combi_list = []
for i in range(1, len(_list) + 1):
    print(list(combinations(_list, i)))
		combi_list.extend(list(combinations(_list, i)))
# [(1,), (2,), (3,)]
# [(1, 2), (1, 3), (2, 3)]
# [(1, 2, 3)]

permutations

순열을 표현할 때 사용되는 메소드이다. 한 리스트에서 중복을 허용하고 모든 경우의 수를 구하는 것이다. 반환되는 항목의 수는 n! / r!이다.

from itertools import permutations

_list = [1, 2, 3]
perm = list(permutations(_list, 2))
print(perm)													# [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

product

데카르트 곱이라고도 하는 cartesian product를 표현할 때 사용하는 메소드이다(DB의 join, 관계 대수의 product를 생각하면 된다). 이 메소드의 특징은 두 개 이상의 리스트의 모든 조합을 구할 때 사용된다.

from itertools import product

_list = ["012", "abc", "!@#"]
pd = list(product(*_list))
# [('0', 'a', '!'), ('0', 'a', '@'), ('0', 'b', '!'), ('0', 'b', '@'), ('1', 'a', '!'), ('1', 'a', '@'), ('1', 'b', '!'), ('1', 'b', '@')]

pd_repeat = list(product(_list, repeat = 2))  # 반복
# [('012', '012'), ('012', 'abc'), ('012', '!@#'), ('abc', '012'), ('abc', 'abc'), ('abc', '!@#'), ('!@#', '012'), ('!@#', 'abc'), ('!@#', '!@#')]

주의할 점

combinationspermutationsproduct 세 메소드 모두 generator이기 때문에 list()로 캐스팅하여 다른 곳에 저장 해두지 않으면 한 번의 루핑 이후 사라지게 된다.

from itertools import combinations

_list = range(4)
combi = combinations(_list, 2)
print(list(combi))		# [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
print(list(combi))		# []

참고 링크

flatten - chain

위의 예제에서, 내부 리스트의 모든 데이터를 하나의 리스트로 만드려면(flatten) itertools를 이용하면 됩니다. flatten을 적용하려면 chain(*list3)처럼 *를 리스트에 붙여주어야 합니다.

import itertools

list1 = [[1, 10], [2, 22], [3, 19]]
list2 = [[4, 2], [5, 9], [6, 3]]

list3 = list(map(list.__add__, list1, list2))
list4 = list(itertools.chain(*list3))
print(list4)

# Output:
# [1, 10, 4, 2, 2, 22, 5, 9, 3, 19, 6, 3]