10강 / 20강

집계와 순위 — 베스트 10을 뽑는 법

한 번만 훑기 · 카운팅 · 전체 정렬 없이 상위 N개

집계와 순위 — 베스트 10을 뽑는 법
100만 건에서 상위 10개만 필요한데, 100만 개를 전부 정렬할 이유가 있을까요?

매일 아침 대표님이 묻습니다. "어제 뭐가 제일 많이 팔렸어?"

어제 주문이 80만 건입니다. 베스트 10을 뽑아야 해요. 가장 먼저 떠오르는 방법은 이렇겠죠.

  1. 상품별 판매량을 센다
  2. 판매량순으로 전부 정렬한다
  3. 앞에서 10개를 자른다

답은 맞습니다. 그런데 3만 종류의 상품을 전부 정렬해 놓고 겨우 10개만 쓰고 버리는 거예요. 낭비죠.

① 한 번만 훑기 — 합계 · 최대 · 평균

이런 값들은 정렬이 필요 없습니다. 한 번 지나가면서 기억해 두면 돼요.

정렬은 O(n log n), 한 번 훑기는 O(n). 정렬이 필요 없으면 하지 마세요.
Python 브라우저에서 실행

② 카운팅 — 딕셔너리로 개수 세기

"상품별 판매량"은 딕셔너리에 세면서 한 바퀴면 끝납니다.

Counter.most_common(n) — 이 한 줄이 오늘의 주인공입니다.
Python 브라우저에서 실행

③ Top-N — 전체를 정렬하지 않고 상위 10개만

여기가 이번 강의 핵심입니다. 힙(heap)이라는 도구를 씁니다.

아이디어는 이렇습니다. 크기 10짜리 상자를 하나 들고 다니면서:

  1. 상자가 안 찼으면 그냥 넣는다
  2. 상자가 찼으면, 상자 안에서 가장 작은 것과 비교한다
  3. 새 값이 더 크면 → 가장 작은 걸 버리고 새 값을 넣는다
  4. 작으면 → 그냥 무시한다 (대부분 여기에 걸립니다!)

상자 크기가 10으로 고정이니 메모리도 10칸이면 됩니다. 80만 건짜리 데이터를 메모리에 다 올리지 않고도 처리할 수 있어요.

heapq.nlargest — 실무에서 Top-N을 뽑는 표준 도구입니다.
Python 브라우저에서 실행

🎮 매출 집계기

주문 데이터를 만들고, 전체 정렬과 힙 Top-N이 각각 몇 번 비교하는지 나란히 재 봅시다. N(뽑을 개수)을 바꾸면 어느 쪽이 유리해지는지도 보입니다.

매출 집계기 — 전체 정렬 vs 힙 Top-N 비교 횟수 실측
불러오는 중…

언제 무엇을 쓸까

필요한 것방법비용
합계 · 평균 · 최대 · 개수한 번 훑기O(n)
항목별 개수CounterO(n)
상위 10개 (n이 아주 큼)heapq.nlargestO(n log k)
상위 절반 이상이 필요그냥 sortedO(n log n)
전체 순위표sortedO(n log n)

k가 n에 가까워지면 힙의 이점이 사라집니다. "n은 아주 큰데 k는 작다"일 때만 힙이 이겨요.

🤔 확인 문제
주문 100만 건에서 총 매출액만 필요합니다. 가장 적절한 방법은?
🤔 확인 문제
상품 500,000종 중 베스트 10만 필요할 때 가장 효율적인 방법은?
🤔 확인 문제
Counter 로 상품별 판매량을 셌습니다. "한 번도 안 팔린 상품" 목록을 구하려면?