본문 바로가기

일::개발

[python] 리스트를 그룹화 itertools.groupby

중복 파일을 제거하기위해 일단 파일 사이즈가 같은 파일을 걸러내려고 한다.

itertools.groupby()를 사용하면 쉽게 될 것 같다.

from itertools import groupby

rows = [('file1.ext', 123123), ('file2.ext', 123123), ('file3.ext', 234234), ('file4.ext', 234234), ('file5.ext', 234234)]
for k, g in groupby(rows, lambda x:x[1]):
	print(list(g))
    
----

[('file1.ext', 123123), ('file2.ext', 123123)]
[('file3.ext', 234234), ('file4.ext', 234234), ('file5.ext', 234234)]

좋다. 

그런데, 아래처럼 list(g) 를 한번 더 호출하면 빈 리스트가 반환된다. 

from itertools import groupby

rows = [('file1.ext', 123123), ('file2.ext', 123123), ('file3.ext', 234234), ('file4.ext', 234234), ('file5.ext', 234234)]
for k, g in groupby(rows, lambda x:x[1]):
    print(list(g))
    print(list(g))

----

[('file1.ext', 123123), ('file2.ext', 123123)]
[]
[('file3.ext', 234234), ('file4.ext', 234234), ('file5.ext', 234234)]
[]

 

groupby()는 아래와 같이 구현되어 있기 때문. 

class groupby(object):
    # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B
    # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
    def __init__(self, iterable, key=None):
        if key is None:
            key = lambda x: x
        self.keyfunc = key
        self.it = iter(iterable)
        self.tgtkey = self.currkey = self.currvalue = object()
    def __iter__(self):
        return self
    def next(self):
        while self.currkey == self.tgtkey:
            self.currvalue = next(self.it)    # Exit on StopIteration
            self.currkey = self.keyfunc(self.currvalue)
        self.tgtkey = self.currkey
        return (self.currkey, self._grouper(self.tgtkey))
    def _grouper(self, tgtkey):
        while self.currkey == tgtkey:
            yield self.currvalue
            self.currvalue = next(self.it)    # Exit on StopIteration
            self.currkey = self.keyfunc(self.currvalue)