파이썬 리스트 요소를 조건에 따라 변환하고 걸러내기

파이썬 리스트 요소를 조건에 따라 변환하고 걸러내기

리스트 요소를 조건에 따라 처리한다는 말에는 서로 다른 세 작업이 섞여 있습니다. 값을 바꾸는 변환, 필요한 값만 남기는 필터링, 원본을 직접 수정하는 작업입니다. 목적을 먼저 구분하면 코드가 단순해집니다.

조건에 따라 새 값 만들기

scores = [42, 75, 91, 58]
adjusted = [score if score >= 60 else 0 for score in scores]

print(scores)    # [42, 75, 91, 58]
print(adjusted)  # [0, 75, 91, 0]

컴프리헨션은 새 리스트를 만들기 때문에 원본은 유지됩니다. 조건 표현식은 모든 요소를 결과에 포함하되 값만 다르게 만듭니다.

조건에 맞는 요소만 남기기

passed = [score for score in scores if score >= 60]
print(passed)  # [75, 91]

이 형태의 뒤쪽 if는 조건을 만족하지 않는 요소를 결과에서 제외합니다. 앞의 예제와 역할이 다릅니다.

복잡한 규칙은 함수로 분리

def normalize_score(score):
    if score < 0:
        return 0
    if score > 100:
        return 100
    return score

raw_scores = [105, 82, -3, 60]
clean_scores = [normalize_score(score) for score in raw_scores]
print(clean_scores)  # [100, 82, 0, 60]

규칙에 이름을 붙이면 무엇을 하는지 드러나고 함수만 따로 테스트할 수 있습니다.

원본 리스트를 직접 바꾸기

scores = [42, 75, 91, 58]

for index, score in enumerate(scores):
    if score < 60:
        scores[index] = 0

원본 변경이 정말 필요한 경우에만 사용하십시오. 다른 코드가 같은 리스트를 참조하고 있다면 예상하지 못한 영향이 생길 수 있습니다.

순회 중 remove를 피해야 하는 이유

# 요소를 건너뛸 수 있는 코드
for score in scores:
    if score < 60:
        scores.remove(score)

삭제로 리스트 길이와 인덱스가 바뀌기 때문에 다음 요소를 건너뛸 수 있습니다. 필터링 컴프리헨션으로 새 리스트를 만들거나 복사본을 순회하십시오.

map과 filter로 표현한 같은 작업

scores = [42, 75, 91, 58]

adjusted = list(map(lambda x: x if x >= 60 else 0, scores))
passed = list(filter(lambda x: x >= 60, scores))

동작은 가능하지만 이 정도 조건에서는 리스트 컴프리헨션이 파이썬 사용자에게 더 익숙하고 읽기 쉽습니다. map()은 이미 이름 있는 함수를 적용할 때 특히 유용합니다.

연습: 상품 가격 정리

가격 목록에서 0 이하인 값은 제외하고, 남은 가격에는 10% 할인을 적용해 새 리스트를 만드십시오. 원본은 유지하고 결과는 정수로 반올림합니다. 필터링과 변환을 한 줄에 모두 넣은 방식과 두 단계로 나눈 방식 중 어느 쪽이 읽기 쉬운지 비교해 보세요.

원본 보존 여부를 테스트로 확인하기

original = [42, 75, 91, 58]
adjusted = [score if score >= 60 else 0 for score in original]

assert original == [42, 75, 91, 58]
assert adjusted == [0, 75, 91, 0]

변환 함수가 새 목록을 반환한다고 약속했다면 원본이 그대로인지도 테스트 대상입니다. 반대로 원본을 수정하는 함수라면 함수 이름과 문서에서 그 사실이 드러나야 합니다.

목록이 매우 크면 새 리스트가 추가 메모리를 사용합니다. 한 번만 순회할 결과라면 제너레이터 표현식을 고려할 수 있지만, 여러 번 사용하거나 길이와 인덱스가 필요하면 리스트가 더 편리합니다. 자료 크기와 사용 방식을 함께 보고 선택하십시오.

정리

값을 바꾸면 조건 표현식이 포함된 컴프리헨션, 일부만 남기면 뒤쪽 if가 있는 컴프리헨션을 사용합니다. 복잡한 규칙은 함수로 분리하고 원본 직접 수정은 필요한 경우로 제한하십시오.