Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬으로 리스트에서 연속된 부울 값 구간의 위치 찾기

값들로 이루어진 리스트가 주어졌을 때, 부울(Boolean) 값이 연속된 구간으로 나타나는 위치를 파악해야 하는 경우가 있습니다. 즉, True 값을 만난 이후에는 False가 나타날 때까지 True가 계속 이어지고, 반대로 False를 만난 이후에는 True가 나타날 때까지 False가 연속되는 방식입니다.

이 글에서는 이러한 연속 구간의 경계 위치를 구하는 두 가지 방법을 소개합니다.

itertools의 accumulate와 groupby 활용

itertools 모듈의 accumulate 함수와 groupby 함수를 함께 사용하면 손쉽게 해결할 수 있습니다. 먼저 groupby로 인접한 동일한 값들을 그룹으로 묶고, 각 그룹의 요소 개수를 세어 accumulate로 누적 합산합니다. 이렇게 하면 각 구간이 끝나는 위치가 순서대로 계산되며, 리스트의 마지막 값은 전체 리스트가 끝나는 마지막 위치가 됩니다.

예제 코드

from itertools import accumulate, groupby

# 주어진 리스트
listA = [False, True, True, False, False]

print("Given list : \n", listA)

# accumulate 적용
res = [0] + list(accumulate(sum(1 for x in y)
for x, y in groupby(listA)))

# 결과 출력
print("Positions for Range of contigous values:\n ", res)

실행 결과

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.

Given list :
[False, True, True, False, False]
Positions for Range of contigous values:
[0, 1, 3, 5]

결과인 [0, 1, 3, 5]는 각각 첫 번째 구간의 시작(0), True 구간의 시작(1), False 구간의 시작(3), 그리고 리스트의 끝(5)을 의미합니다.

enumerate와 zip 활용

또 다른 방법은 enumerate 함수와 zip 함수를 조합하는 것입니다. 각 요소를 바로 다음 요소와 비교하여, 두 값이 서로 다른 지점을 새로운 연속 구간의 시작 위치로 판단합니다. 리스트 앞뒤에 임의의 센티널 값(예: 2)을 추가함으로써 리스트의 양 끝 경계도 자연스럽게 처리할 수 있습니다.

예제 코드

# 주어진 리스트
listA = [False, True, True, False, False]

print("Given list : \n", listA)

# enumerate 적용
res = [e for e, (x, y) in
enumerate(zip([2] + listA, listA + [2])) if x != y]

# 결과 출력
print("Positions for Range of contigous values:\n ", res)

실행 결과

위 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.

Given list :
[False, True, True, False, False]
Positions for Range of contigous values:
[0, 1, 3, 5]

마무리

두 방법 모두 동일한 결과를 반환하지만, itertools를 사용하는 방식은 코드의 의도가 더 명확하게 드러나는 장점이 있고, enumeratezip을 사용하는 방식은 추가 모듈 없이 한 줄의 리스트 컴프리헨션으로 간결하게 처리할 수 있다는 장점이 있습니다. 상황에 맞게 선택하여 활용하시기 바랍니다.