# python3.8 defaccumulate(iterable, func=operator.add, *, initial=None): it = iter(iterable) total = initial if initial isNone: try: total = next(it) except StopIteration: return yield total for element in it: total = func(total, element) yield total
# python3.7 이하 defaccumulate(iterable, func=operator.add): it = iter(iterable) try: total = next(it) except StopIteration: return yield total for element in it: total = func(total, element) yield total
defzip_longest(*args, fillvalue=None): iterators = [iter(it) for it in args] num_active = len(iterators) ifnot num_active: return whileTrue: values = [] for i, it in enumerate(iterators): try: value = next(it) except StopIteration: num_active -= 1 ifnot num_active: return iterators[i] = repeat(fillvalue) value = fillvalue values.append(value) yield tuple(values)
zip_longest를 예제에 앞서 내장함수 zip에 대해 알아보겠습니다.
zip은 길이가 짧은 인자를 기준으로 요소들을 결합한 배열을 반환합니다.
'abc'가 'ㄱㄴㄷㄹㅁ' 보다 길이가 짧으므로 'abc' 기준으로 결과가 반환 된 것을 볼 수 있습니다.
1 2 3 4 5
list(zip('abc', 'ㄱㄴㄷㄹㅁ'))
""" [('a', 'ㄱ'), ('b', 'ㄴ'), ('c', 'ㄷ')] """
zip_longest는 길이가 긴 'ㄱㄴㄷㄹㅁ'를 기준으로 모자란 부분은 None을 채워서 반환하는 것을 볼 수 있습니다.
defproduct(*args, repeat=1): pools = [tuple(pool) for pool in args] * repeat result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yield tuple(prod)
'ABCD'와 'xy'의 곱집합인 'Ax Ay Bx By Cx Cy Dx Dy'를 반환하는 예제입니다.
defpermutations(iterable, r=None): pool = tuple(iterable) n = len(pool) r = n if r isNoneelse r if r > n: return indices = list(range(n)) cycles = list(range(n, n-r, -1)) yield tuple(pool[i] for i in indices[:r]) while n: for i in reversed(range(r)): cycles[i] -= 1 if cycles[i] == 0: indices[i:] = indices[i+1:] + indices[i:i+1] cycles[i] = n - i else: j = cycles[i] indices[i], indices[-j] = indices[-j], indices[i] yield tuple(pool[i] for i in indices[:r]) break else: return
순열의 개수는 다음과 같이 구할 수 있습니다.
nPr = n!/(n-r)!
두 번째 인자는 iterable에서 뽑는 개수이므로 len(iterable) 보다 클 수 없습니다.
조합을 의미하는 combinations는 n개 중에서 r를 뽑아 만들 수 있는 집합(set)의 나열입니다. (한 번 뽑은 인자는 다시 뽑을 수 없습니다.)
python3.8 combinations function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
defcombinations(iterable, r): pool = tuple(iterable) n = len(pool) if r > n: return indices = list(range(r)) yield tuple(pool[i] for i in indices) whileTrue: for i in reversed(range(r)): if indices[i] != i + n - r: break else: return indices[i] += 1 for j in range(i+1, r): indices[j] = indices[j-1] + 1 yield tuple(pool[i] for i in indices)
위에서 설명한 combinations과 달리 한 번 뽑은 인자를 다시 뽑을 수 있는 경우의 조합입니다.
python3.8 combinations_with_replacement
1 2 3 4 5 6 7 8 9 10 11 12 13 14
pool = tuple(iterable) n = len(pool) ifnot n and r: return indices = [0] * r yield tuple(pool[i] for i in indices) whileTrue: for i in reversed(range(r)): if indices[i] != n - 1: break else: return indices[i:] = [indices[i] + 1] * (r - i) yield tuple(pool[i] for i in indices)