이번 편의 목표: 리스트 컴프리헨션과 key 함수를 사용합니다.

지출이 쌓이면 전부 출력하는 것만으로는 부족합니다. 만 원 이상 쓴 내역만 보고 싶거나, 금액이 큰 순서대로 보고 싶어집니다. 이번 편에서는 이미 있는 자료에서 보고 싶은 목록을 새로 만드는 방법을 배웁니다.

긴 반복을 짧게 표현하기

Python
expenses = [
    {"item": "커피", "amount": 4500},
    {"item": "책", "amount": 18000},
    {"item": "점심", "amount": 12000},
]

large = [row for row in expenses if row["amount"] >= 10000]
print(large)
amounts = [row["amount"] for row in expenses]
print(amounts)

ranked = sorted(expenses, key=lambda row: row["amount"], reverse=True)
for row in ranked:
    print(f"{row['item']}: {row['amount']:,}원")
print(expenses[0]["item"])

첫 줄의 컴프리헨션은 `expenses`에서 한 건씩 꺼내고, 금액이 만 원 이상인 `row`만 새 리스트에 담습니다. 보통 반복문으로 빈 리스트를 만들고 `append()`하던 작업을 한 줄로 표현한 것입니다. 읽는 순서는 `for`의 자료 출처, `if`의 조건, 맨 앞의 담을 값입니다.

`amounts`는 거래 전체 대신 금액만 뽑아 `[4500, 18000, 12000]`을 만듭니다. 필터링과 변환은 서로 다른 작업이지만 한 컴프리헨션 안에서 함께 쓸 수도 있습니다.

정렬 기준을 전달한다

`sorted()`는 정렬된 새 리스트를 반환합니다. 원래 `expenses`의 첫 항목은 여전히 `커피`입니다. 원본 목록의 순서를 직접 바꾸는 `list.sort()`와 구별해야 합니다.

딕셔너리 자체를 어떤 순서로 비교할지는 모호하므로 `key`로 기준을 전달합니다. `lambda row: row["amount"]`는 한 건을 받아 그 금액을 돌려주는 작은 함수입니다. 함수의 일반적인 작성법은 다음 편에서 배웁니다. 지금은 “각 행에서 금액을 꺼내 비교한다”라고 읽으면 됩니다.

`reverse=True`는 큰 값부터 정렬합니다. 같은 키를 가진 요소들은 원래 상대 순서가 유지됩니다. 금액이 같을 때 항목 이름도 기준으로 삼으려면 튜플을 반환하는 키를 쓸 수 있지만, 기준이 복잡해지면 이름 있는 함수로 나누는 편이 낫습니다.

짧음보다 읽기 쉬움

컴프리헨션 안에 여러 반복문과 조건문을 겹치면 한 줄이 오히려 이해하기 어려워집니다. “입력을 정리하고, 오류를 기록하고, 성공한 자료만 담는다”처럼 단계가 많다면 일반 `for`문이 더 적합합니다.

또한 새 리스트를 만들었다고 내부 딕셔너리까지 복사되는 것은 아닙니다. `large[0]`과 원본의 해당 행은 같은 객체일 수 있습니다. 조회 결과를 수정할 계획이라면 다음의 복사 개념까지 확인해야 합니다.

직접 해 보기

`[900, 1200, 5000, 700]`에서 천 원 이상만 골라 오름차순으로 정렬하세요. 원본 목록은 유지하세요.

해설

Python
amounts = [900, 1200, 5000, 700]
selected = [amount for amount in amounts if amount >= 1000]
ordered = sorted(selected)
print(ordered)
print(amounts)

결과는 `[1200, 5000]`, `[900, 1200, 5000, 700]`입니다. 필터링 결과와 정렬 결과에 각각 이름을 붙이면 중간 과정을 확인하기도 쉽습니다.