10강 / 20강
집계와 순위 — 베스트 10을 뽑는 법
한 번만 훑기 · 카운팅 · 전체 정렬 없이 상위 N개
매일 아침 대표님이 묻습니다. "어제 뭐가 제일 많이 팔렸어?"
어제 주문이 80만 건입니다. 베스트 10을 뽑아야 해요. 가장 먼저 떠오르는 방법은 이렇겠죠.
- 상품별 판매량을 센다
- 판매량순으로 전부 정렬한다
- 앞에서 10개를 자른다
답은 맞습니다. 그런데 3만 종류의 상품을 전부 정렬해 놓고 겨우 10개만 쓰고 버리는 거예요. 낭비죠.
① 한 번만 훑기 — 합계 · 최대 · 평균
이런 값들은 정렬이 필요 없습니다. 한 번 지나가면서 기억해 두면 돼요.
정렬은 O(n log n), 한 번 훑기는 O(n). 정렬이 필요 없으면 하지 마세요.
Python
브라우저에서 실행
② 카운팅 — 딕셔너리로 개수 세기
"상품별 판매량"은 딕셔너리에 세면서 한 바퀴면 끝납니다.
Counter.most_common(n) — 이 한 줄이 오늘의 주인공입니다.
Python
브라우저에서 실행
③ Top-N — 전체를 정렬하지 않고 상위 10개만
여기가 이번 강의 핵심입니다. 힙(heap)이라는 도구를 씁니다.
아이디어는 이렇습니다. 크기 10짜리 상자를 하나 들고 다니면서:
- 상자가 안 찼으면 그냥 넣는다
- 상자가 찼으면, 상자 안에서 가장 작은 것과 비교한다
- 새 값이 더 크면 → 가장 작은 걸 버리고 새 값을 넣는다
- 작으면 → 그냥 무시한다 (대부분 여기에 걸립니다!)
상자 크기가 10으로 고정이니 메모리도 10칸이면 됩니다. 80만 건짜리 데이터를 메모리에 다 올리지 않고도 처리할 수 있어요.
heapq.nlargest — 실무에서 Top-N을 뽑는 표준 도구입니다.
Python
브라우저에서 실행
🎮 매출 집계기
주문 데이터를 만들고, 전체 정렬과 힙 Top-N이 각각 몇 번 비교하는지 나란히 재 봅시다. N(뽑을 개수)을 바꾸면 어느 쪽이 유리해지는지도 보입니다.
언제 무엇을 쓸까
| 필요한 것 | 방법 | 비용 |
|---|---|---|
| 합계 · 평균 · 최대 · 개수 | 한 번 훑기 | O(n) |
| 항목별 개수 | Counter | O(n) |
| 상위 10개 (n이 아주 큼) | heapq.nlargest | O(n log k) |
| 상위 절반 이상이 필요 | 그냥 sorted | O(n log n) |
| 전체 순위표 | sorted | O(n log n) |
k가 n에 가까워지면 힙의 이점이 사라집니다. "n은 아주 큰데 k는 작다"일 때만 힙이 이겨요.
🤔 확인 문제
주문 100만 건에서 총 매출액만 필요합니다. 가장 적절한 방법은?
해설 합계는 순서와 무관합니다. 한 번 훑기 O(n)이면 충분해요. 정렬은 O(n log n)으로 필요 없는 일을 하는 겁니다.
🤔 확인 문제
상품 500,000종 중 베스트 10만 필요할 때 가장 효율적인 방법은?
해설 O(n log k)입니다. k=10이므로 사실상 O(n)에 가까워요. 전체 정렬 O(n log n)보다 훨씬 쌉니다.
🤔 확인 문제
Counter 로 상품별 판매량을 셌습니다. "한 번도 안 팔린 상품" 목록을 구하려면?
해설 Counter 에는 한 번이라도 등장한 것만 담깁니다. 0인 항목은 아예 없어요. 전체 - 팔린 것 차집합(9강)이 정답입니다.