튜플로 이루어진 리스트에서 양방향(bidirectional) 쌍, 즉 (a, b)와 (b, a)처럼 요소 순서만 서로 뒤바뀐 튜플 조합의 개수를 세야 하는 경우가 있습니다.
이런 개수를 계산하려면 중첩 반복문으로 리스트의 모든 튜플 조합을 비교한 뒤, 한 튜플의 첫 번째 요소가 다른 튜플의 두 번째 요소와 일치하고 그 반대도 성립하는지 'AND' 연산으로 동시에 검사하면 됩니다.
예제 코드
my_list = [(45, 67), (11, 23), (67, 45), (23, 11), (0, 9), (67, 45)]
print("리스트 :");
print(my_list)
my_result = 0
for idx in range(len(my_list)):
for iidx in range(idx + 1, len(my_list)):
# (a, b) 와 (b, a) 형태인지 검사
if my_list[idx][0] == my_list[iidx][1] and my_list[idx][1] == my_list[iidx][0]:
my_result += 1
print("양방향 쌍의 개수 :");
print(my_result)실행 결과
리스트 : [(45, 67), (11, 23), (67, 45), (23, 11), (0, 9), (67, 45)] 양방향 쌍의 개수 : 3
코드 설명
튜플로 구성된 리스트를 정의하고 콘솔에 출력합니다.
결과를 저장할 변수
my_result를 0으로 초기화합니다.외부 반복문과 내부 반복문을 사용해 리스트를 두 겹으로 순회하며 모든 쌍을 비교합니다.
내부 반복문은
idx + 1부터 시작하므로 자기 자신과의 비교, 이미 검사한 조합의 중복 비교를 자연스럽게 피할 수 있습니다.조건문에서 'AND' 연산으로 두 조건을 동시에 확인합니다. 즉, 앞 튜플의 첫 번째 요소가 뒤 튜플의 두 번째 요소와 같고, 앞 튜플의 두 번째 요소가 뒤 튜플의 첫 번째 요소와 같은지 검사합니다.
두 조건이 모두 참이면 양방향 쌍으로 판정하여 결과 변수를 1씩 증가시킵니다.
반복이 끝난 후 최종 개수를 콘솔에 출력합니다.
위 예제에서 (45, 67)–(67, 45) 조합이 두 번, (11, 23)–(23, 11) 조합이 한 번 발견되므로 결과는 3이 됩니다. 참고로 리스트에 (67, 45)가 두 번 등장하지만, 동일한 인덱스끼리는 비교하지 않으므로 자기 자신과는 짝을 이루지 않습니다.
더 파이썬다운 방법: itertools 활용
중첩 반복문 대신 itertools.combinations를 사용하면 코드를 더 간결하게 만들 수 있습니다.
from itertools import combinations
my_list = [(45, 67), (11, 23), (67, 45), (23, 11), (0, 9), (67, 45)]
count = sum(
1 for a, b in combinations(my_list, 2)
if a[0] == b[1] and a[1] == b[0]
)
print(count) # 출력: 3combinations(my_list, 2)는 가능한 모든 두 원소 조합을 생성하며, 제너레이터 표현식과 sum()을 조합해 조건을 만족하는 쌍의 개수를 한 줄로 계산합니다. 데이터 크기가 커질 때는 가독성과 유지보수 측면에서 이 방식이 더 유리합니다.