개요
파이썬에서 두 개의 리스트에 담긴 요소들을 K개씩 번갈아 가며 교차 조인(cross join)해야 하는 경우가 있습니다. 즉, 첫 번째 리스트에서 K개의 요소를 가져온 직후 두 번째 리스트에서 K개의 요소를 가져오는 방식으로 하나의 새로운 시퀀스를 만드는 것입니다.
이러한 작업은 제너레이터(generator) 함수와 yield 키워드를 활용하면 효율적으로 구현할 수 있습니다. 아래 예제에서는 반복문으로 인덱스를 순차적으로 증가시키면서 요소를 하나씩 생성(yield)하는 메서드를 정의합니다.
예제
다음은 두 리스트의 요소를 K개씩 교차로 병합하는 전체 코드입니다.
def merge_pair_elem(my_list_1, my_list_2, K):
index_1 = 0
index_2 = 0
while(index_1 < len(my_list_1)):
for i in range(K):
yield my_list_1[index_1]
index_1 += 1
for i in range(K):
yield my_list_2[index_2]
index_2 += 1
my_list_1 = [24, 13, 82, 22, 65, 74]
my_list_2 = [55, 63, 17, 44, 33, 15]
print("첫 번째 리스트 :")
print(my_list_1)
print("두 번째 리스트 :")
print(my_list_2)
K = 1
print("K의 값 :")
print(K)
my_result = [element for element in merge_pair_elem(my_list_1, my_list_2, K)]
print("결과는 다음과 같습니다 :")
print(my_result)출력
첫 번째 리스트 : [24, 13, 82, 22, 65, 74] 두 번째 리스트 : [55, 63, 17, 44, 33, 15] K의 값 : 1 결과는 다음과 같습니다 : [24, 55, 13, 63, 82, 17, 22, 44, 65, 33, 74, 15]
코드 설명
merge_pair_elem이라는 이름의 제너레이터 함수가 정의되며, 두 개의 리스트와 K 값을 매개변수로 받습니다.
함수 내부에는 index_1과 index_2 두 개의 인덱스 변수가 선언되어 각 리스트에서 현재 읽어야 할 위치를 추적합니다.
while 루프는 첫 번째 리스트의 끝에 도달할 때까지 실행되며, 내부의 for 루프가 K번씩 반복하면서 각 리스트의 요소를 yield로 하나씩 반환합니다.
함수 외부에서는 정수로 이루어진 두 개의 리스트가 정의되고 콘솔에 출력됩니다.
K 값은 1로 설정되었으며, 이 경우 두 리스트의 요소가 하나씩 번갈아 배치됩니다.
리스트 컴프리헨션(list comprehension)으로 제너레이터가 생성하는 요소들을 순회한 뒤, 그 결과를 리스트로 변환하여 변수에 할당합니다.
최종 결과 리스트가 콘솔에 출력됩니다.
추가 팁
K 값을 2로 바꾸면 첫 번째 리스트에서 2개, 두 번째 리스트에서 2개씩 번갈아 가져오게 됩니다. 참고로 위 제너레이터 방식은 첫 번째 리스트가 더 짧으면 두 번째 리스트의 남은 요소가 무시되고, 반대로 두 번째 리스트가 더 짧으면 IndexError가 발생할 수 있으므로 두 리스트의 길이가 비슷할 때 사용하는 것이 좋습니다.
같은 결과는 슬라이싱을 이용해 더 간결하게 얻을 수도 있습니다.
def merge_pair_elem(my_list_1, my_list_2, K):
result = []
for i in range(0, len(my_list_1), K):
result.extend(my_list_1[i:i + K])
result.extend(my_list_2[i:i + K])
return result다만 대용량 데이터를 다룰 때는 제너레이터가 중간 결과를 메모리에 저장하지 않고 요소를 하나씩 생성하므로 메모리 사용 측면에서 더 유리합니다.