파이썬 zip 함수 : 반복자 쌍들을 가지고 노는 함수

들어가면서

저는 2개의 iterable 객체를 동시에 반복문으로 돌릴 때 “파이썬 zip 함수”를 너무 유용하게 사용하였습니다. 그렇게 유용하게 사용하던 zip 함수지만 모르는 특징이 있었다는 걸 깨닫고 블로그 글로 정리해보게 되었습니다.

zip 함수 ?

Python에서 zip() 함수는 여러 iterable 항목(예: 리스트, 튜플 또는 문자열)을 튜플의 반복자로 결합하는 데 사용됩니다.

zip 함수는 이런 기능을 이용해서 병렬 반복이나 데이터 쌍과 같은 작업에 유용하게 사용 할 수 있습니다.

zip 함수 사용법

2개의 반복 가능 객체를 할당하고 zip함수에 인자로 넘기면 zip 함수가 어떻게 작동하는지 바로 파악 할 수 있습니다.

numbers = [1, 2, 3]
letters = ['a', 'b', 'c']

zipped = zip(numbers, letters)

for pair in zipped:
    print(pair)

output

(1, 'a')
(2, 'b')
(3, 'c')

이 예에서 zip()숫자 목록과 문자 목록을 튜플의 반복자로 결합합니다. 각 튜플에는 숫자의 요소 하나와 문자의 요소 하나가 포함되어 있으며 해당 위치를 기준으로 함께 쌍을 이룹니다.

두 iterable 객체의 길이가 다른 경우

입력 반복 가능 항목의 길이가 다른 경우 ‘zip()’은 가장 짧은 입력 반복 가능 항목이 소진되는 즉시 튜플 생성을 중지하게 됩니다.

numbers = [1, 2, 3, 4]
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']

zipped = zip(numbers, letters)

for pair in zipped:
    print(pair)

output

(1, 'a')
(2, 'b')
(3, 'c')
(4, 'd')

3개 이상의 iterable 항목도 인자로 받을 수 있다

이 특성이 이번에 새롭게 알게 된 zip 함수의 특성입니다. 저는 2개의 인자 받는 걸로 고정이 되어있는 줄…

zip 함수는 동일한 인덱스 위치에 있는 각 반복 가능 요소로 튜플을 생성 할 수 있습니다.

numbers = [1, 2, 3]
letters = ['a', 'b', 'c']
symbols = ['!', '@', '#']

zipped = zip(numbers, letters, symbols)

for triplet in zipped:
    print(triplet)

output

(1, 'a', '!')
(2, 'b', '@')
(3, 'c', '#')

symmetric matrix 검사에 활용

다음과 같은 symmetric matrix 검사에 활용 할 수 있습니다.

이차원 배열의 [i][j]와 [j][i]가 동일한지, 다시 말해 대칭구조로 이루어진 매트릭스인지 확인하는 함수를 구현하는 문제입니다.

정말 간단하게 이중 for문으로 해결할 수 있는 문제인데요. zip 함수로도 이 문제를 해결 할 수 있습니다.

이중 for문으로 구현 시

def solution(arr):
    n = len(arr)
    for i in range(n):
        for j in range(n):
            if arr[i][j] != arr[j][i]:
                return 0
    return 1

zip 함수로 구현 시

def solution(arr):
    return int(arr == list(map(list, zip(*arr))))

딕셔너리를 병렬로 처리

Python 3.6 이상에서는 사전이 순서가 지정된 collection입니다.

이 기능을 활용하면 Python zip() 함수를 사용하여 안전하고 일관된 방식으로 여러 사전을 반복할 수 있습니다.

dict_one = {'name': 'John', 'last_name': 'Doe', 'job': 'Python Consultant'}
dict_two = {'name': 'Jane', 'last_name': 'Doe', 'job': 'Community Manager'}
for (k1, v1), (k2, v2) in zip(dict_one.items(), dict_two.items()):
    print(k1, '->', v1)
    print(k2, '->', v2)

output

name -> John
name -> Jane
last_name -> Doe
last_name -> Doe
job -> Python Consultant
job -> Community Manager

unzipping 시퀀스

zip() 함수를 이용해 병렬로 만들어진 튜플을 다시 n개의 튜플로 변환 할 수 있습니다.

이를 위해서는 unzip()과 같은 함수를 이용하는 게 아니라 동일한 zip함수 인데 unpacking 연산자인 * 를 활용합니다.


pairs = [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]
numbers, letters = zip(*pairs)
print(numbers)  # (1, 2, 3, 4)
print(letters)  # ('a', 'b', 'c', 'd')

iterable 요소 쌍을 딕셔너리로 만들기

Python의 사전은 매우 유용한 데이터 구조입니다.

때로는 서로 다르지만 밀접하게 관련된 두 시퀀스에서 사전을 구축해야 할 수도 있습니다.

이를 달성하는 편리한 방법은 dict()와 zip()을 함께 사용하는 것입니다.

fields = ['name', 'last_name', 'age', 'job']
values = ['John', 'Doe', '45', 'DBA']

print(dict(zip(fields, values)))
# {'name': 'John', 'last_name': 'Doe', 'age': '45', 'job': 'DBA'}

마치며

“데이터 쌍” 과 관련된 문제다? 그러면 파이썬의 zip 함수부터 떠오르면 좋을 것 같습니다.

참고하면 좋은 글

Leave a Comment

목차