islice
형태: itertools.islice(seq, [start,] stop [,step])
역할: 주어진 sequence를 start:stop:step으로 잘라서 그 원소를 돌려주는 역할을 한다.
예
import itertools
for c in itertools.islice('ABCDEFG', 2):
print(c, end=" ")
print()
for c in itertools.islice('ABCDEFG', 2, None):
print(c, end=" ")
결과는 다음과 같다.
A B
C D E F G
즉, 인수 2개만 주면, seq, stop으로 해석하므로, [:2] 까지의 원소를 돌려준다. 그러나 islice만으로는 어떠한 결과를 보여주지 않고 그저 iterator만을 돌려줄 뿐이다. 그러므로 print(c)를 해야지 그 결과를 볼 수 있다.
두번째 예에서는, 인수가 3개이므로, seq, start, stop으로 해석한다. 즉, 생략된 부분은 앞에서부터 인식하여 중간의 인수는 start로 간주한다. start이 2이고 stop이 None이 된다. 그러므로 [2:]의 원소를 돌려준다.
tee
형태: itertools.tee(it[, n=2])
역할: it에 대해 복사본을 n개 만큼 만든다. n개를 지정하지 않으면 기본으로 2개를 복사한다.
from itertools import tee
i1, i2, i3 = tee(range(5), 3)
print(i1)
print(list(i1))
print(list(i1))
print(list(i2))
print(list(i2))
print(list(i3))
print(list(i3))
위의 예를 실행시키면 range(5)에 해당하는 iterator가 3개 복사되어 i1, i2, i3에 저장된다. 그런데 이것은 iterator이므로 한 번 그 값이 실제로 list 등으로 print 되고 나면 더이상 액세스 할 값이 없게 되므로 다음 결과가 보여진다.
<itertools._tee object at 0x7f3a4db0db00>
[0, 1, 2, 3, 4]
[]
[0, 1, 2, 3, 4]
[]
[0, 1, 2, 3, 4]
[]
groupby
형태: itertools.groupby(iterable[, key])
역할: key값 별로 분류된 sub-iterators를 돌려준다.
예1: s = '424212' 를 각 대표 숫자를 키로 하여 각 숫자를 원소로 갖는 리스트와 묶은 다음, look-and-say, 즉 1개의 1, 3개의 2, 2개의 4를 나타내는 '113224'로 만들어 본다.
from itertools import groupby
s = '424212'
for k, v in groupby(sorted(s)):
print(k, list(v))
''.join(str(len(list(v))) + k for k, v in groupby(sorted(s)))
위 사례에서는 groupby에 정렬된 s를 넣어주었는데, 이 과정에서 정렬은 꼭 필요한 과정이다.
예2: 학생명과 성적으로 묶인 튜플(학생별 성적은 중복하여 존재 가능)을 {학생:[성적]}인 dict로 변환
from itertools import groupby
scores = [('Ryan', 99), ('Muzi', 90), ('Jay-Z', 64), ('Muzi', 93), ('Ryan', 100)]
scores.sort(key=lambda x: x[0]) # MUST HAVE
dic = {key: sorted(map(lambda x: x[1], value))
for key, value in groupby(scores, key=lambda x: x[0])}
print(dic)
(학생명, 성적)은 scores라는 리스트의 원소로 추가되어 있다. 이를 먼저 학생명으로 정렬한 후에, groupby한 결과를 list comprehension으로 dict에 넣어준다. 이 때, 들어갈 내용은 key: [value]이다. 만일 아래와 같이 한다면 결과는 다음과 같다.
for key, value in groupby(scores, key=lambda x: x[0]):
print(key, list(value))
'''
Jay-Z [('Jay-Z', 64)]
Muzi [('Muzi', 90), ('Muzi', 93)]
Ryan [('Ryan', 99), ('Ryan', 100)]
'''
각 value는 결국 원소들을 key로 그루핑한 iterators들이다. 이를 list로 변환하여 우리가 눈으로 볼 수 있게 만들어 프린트 해 본 것이다. 이 중에서 성적만을 추출하려면 sorted(map(lambda x: x[1], value)) 라고 해주어야 한다. 여기서 sorted가 빠지면 {'Jay-Z': <map object at 0x7f3a4dac1ac0>, 'Muzi': <map object at 0x7f3a4dac1490>, 'Ryan': <map object at 0x7f3a4dac1880>} 라고 나타나므로 안되며, map 없이 value[1] 라고만 해도 TypeError: 'itertools._grouper' object is not subscriptable 에러가 발생한다. 굉장히 까다롭다.
product
마지막은 여러 set으로 부터 곱집합을 만들어주는 함수이다.
list(itertools.product('abc', '123', 'XY'))
'''
[('a', '1', 'X'),
('a', '1', 'Y'),
('a', '2', 'X'),
('a', '2', 'Y'),
('a', '3', 'X'),
('a', '3', 'Y'),
('b', '1', 'X'),
('b', '1', 'Y'),
('b', '2', 'X'),
('b', '2', 'Y'),
('b', '3', 'X'),
('b', '3', 'Y'),
('c', '1', 'X'),
('c', '1', 'Y'),
('c', '2', 'X'),
('c', '2', 'Y'),
('c', '3', 'X'),
('c', '3', 'Y')]
'''
'IT in General > Python' 카테고리의 다른 글
Immutable vs mutable (0) | 2023.10.22 |
---|---|
Iterator와 Generator 사용방법 (0) | 2023.03.15 |
any와 all, 그리고 return (0) | 2022.03.25 |
데코레이터와 피보나치 (0) | 2022.03.03 |
functools.reduce (0) | 2022.03.02 |