들어가면서
저는 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 함수부터 떠오르면 좋을 것 같습니다.