Python 라이브러리 - itertools

공식 문서 링크

source code 링크

itertools.cycle

itertools.cycle은 반복 가능한 객체(iterable)를 순서대로 무한히 반복하는 이터레이터를 생성하는 함수입니다.

예시

import itertools 

emp_pool = itertools.cycle(['kim', 'lee', 'park'])

print(next(emp_pool))       # kim
print(next(emp_pool))       # lee
print(next(emp_pool))       # park
print(next(emp_pool))       # kim

참고로 next()는 python 내장 함수로, 이터레이터의 다음 요소를 반환하는 함수입니다.

itertools.accumulate

itertools.accumulate는 반복 가능한 객체(iterable)의 누적합을 계산하여 이터레이터로 반환하는 함수입니다.

예시 - 1

1월부터 12월까지의 월별 누적 합계를 구하는 프로그램입니다.

monthly_income = [1161, 1234, 3421, 1923, 234, 2311, 1000, 1800, 1982, 2023, 2122, 2200]
result = list(itertools.accumulate(monthly_income))

print(result)   # [1161, 2395, 5816, 7739, 7973, 10284, 11284, 13084, 15066, 17089, 19211, 21411]

예시 - 2

1월부터 12월 동안 그때까지의 최대 월 수입을 표시하는 프로그램입니다.

result_2 = list(itertools.accumulate(monthly_income, max))
print(result_2) # [1161, 1234, 3421, 3421, 3421, 3421, 3421, 3421, 3421, 3421, 3421, 3421]

itertools.accumulate() 함수의 두 번째 인수로 max를 전달하면 됩니다.

itertools.groupby

itertools.groupby(iterable, key=None)은 반복 가능한 객체를 키값으로 분류하고 그 결과를 반환하는 함수입니다.

예시

itertools.groupby()함수를 사용해 혈액형별로 묶어 데이터를 분류하는 예시입니다.

import operator
import pprint
import itertools

data = [
    {'name': 'kim', 'blood': 'O'},
    {'name': 'lee', 'blood': 'B'},
    {'name': 'park', 'blood': 'B'},
    {'name': 'choi', 'blood': 'AB'},
    {'name': 'cho', 'blood': 'A'},
    {'name': 'jung', 'blood': 'B'},
    {'name': 'ki', 'blood': 'O'},
]

data = sorted(data, key=operator.itemgetter('blood'))  # groupby-1)
pprint.pprint(data)     # groupby-2)
# [{'blood': 'A', 'name': 'cho'},
#  {'blood': 'AB', 'name': 'choi'},
#  {'blood': 'B', 'name': 'lee'},
#  {'blood': 'B', 'name': 'park'},
#  {'blood': 'B', 'name': 'jung'},
#  {'blood': 'O', 'name': 'kim'},
#  {'blood': 'O', 'name': 'ki'}]

grouped_data = itertools.groupby(data, key=operator.itemgetter('blood'))    # groupby-3)
result = {}
for key, grouped_data in grouped_data:  # groupby-4)
    result[key] = list(grouped_data)

pprint.pprint(result)
# {'A': [{'blood': 'A', 'name': 'cho'}],
#  'AB': [{'blood': 'AB', 'name': 'choi'}],
#  'B': [{'blood': 'B', 'name': 'lee'},
#        {'blood': 'B', 'name': 'park'},
#        {'blood': 'B', 'name': 'jung'}],
#  'O': [{'blood': 'O', 'name': 'kim'}, {'blood': 'O', 'name': 'ki'}]}

groupby-1)

itertools.groupby() 함수를 사용하기 전에 먼저 분류 기준인 혈액형 순으로 정렬합니다. 혈액형으로 정렬하지 않고 itertools.goupby()를 사용하면 분류 기준이 바뀔 때마다 그룹이 생성되므로 원하는 결과를 얻을 수 없습니다.
참고로 중렬을 하기 위해 `operator.itemgetter('blood')를 사용했습니다.
operator.itemgetter() 함수 관련 글 링크

groupby-2)

pprint() 함수 관련 글 링크

groupby-3)

itertools.groupby() 또한 데이터를 혈액형별로 나누어야 하므로 키 항목을 key=operator.itemgetter('blood')와 같이 사용되었습니다. itertools.groupby()는 (분류 기준, 분류 기준으로 묶은 데이터)와 같은 튜플 형식으로 이터레이터를 반환합니다. 따라서 결과를 만들기 위해 groupby-4)의 for문을 통해 변환해야합니다.

itertools.zip_longest

itertools.zip_longest(*iterables, fillvalue=None)함수는 같은 개수의 자료형을 묶는 파이썬 내장 함수인 zip()과 똑같이 동작합니다. 하지만, itertools.zip_longest() 함수는 전달한 반복 가능 객체(*iterables)의 길이가 다르다면 긴 것을 기준으로 빠진 값은 fillvalue에 설정한 값으로 채웁니다.

예시

zip

students = ['jason', 'jake', 'kim', 'finn', 'sane']
teachers = ['lee', 'ki']

result = zip(students, teachers)
print(list(result)) # [('jason', 'lee'), ('jake', 'ki')]

students와 teachers의 개수가 다르면 teachers 개수만큼 zip()으로 묶습니다.

반면 itertools.zip_longest()를 사용하면 개수가 많은 것을 기준으로 묶을 수 있습니다. 이때 부족한 항목은 None으로 채우는데, 아래 코드처럼 fillvalue 값을 지정하면 지정한 값으로 채울 수 있습니다.

import itertools

result = itertools.zip_longest(students, teachers, fillvalue='park')
print(list(result))
# [('jason', 'lee'), ('jake', 'ki'), ('kim', 'park'), ('finn', 'park'), ('sane', 'park')]

itertools.permutations

itertools.permutations(iterable, r=None)은 반복 가능한 객체 중에서 r개를 선택한 순열을 반환하는 함수입니다.

이 모듈을 사용하면 순열을 간단하게 구할 수 있습니다.

예시

아래 코드는 1, 2, 3의 순열을 구하는 코드입니다.

import itertools 

print(list(itertools.permutations(['1', '2', '3'], 2)))
# [('1', '2'), ('1', '3'), ('2', '1'), ('2', '3'), ('3', '1'), ('3', '2')]

itertools.combinations

itertools.combinations(iterable, r)은 반복 가능 객체 중에서 r개를 선택한 조합을 이터레이터로 반환하는 함수입니다.

예시

아래는 10개의 숫자중 3개를 선택하는 경우의 수를 구하는 코드입니다.

import itertools

it = itertools.combinations(range(1, 11), 3)

for num in it:
    print(num)
# (1, 2, 3)
# (1, 2, 4)
# (1, 2, 5)
#     ... 
# (7, 8, 10)
# (7, 9, 10)
# (8, 9, 10)

순환하여 출력하지 않고 이터레이터의 개수만 세려면 아래 코드처럼 하면 됩니다.

print(len(list(itertools.combinations(range(1, 11), 3))))   # 120

만약 중복을 허용하는 조합은 itertools.combinations_with_replacement()를 사용하면 됩니다.

print(len(list(itertools.combinations_with_replacement(range(1, 11), 3))))  # 220

 

 

 

 

'Python > Python' 카테고리의 다른 글

glob.glob() 함수  (0) 2023.06.11
Python 라이브러리 - functools  (0) 2023.05.24
Python 라이브러리 - operator.itemgetter  (0) 2023.05.18
Python 라이브러리 - statistics  (0) 2023.05.17
Python 라이브러리 - random  (0) 2023.05.17