Kotlin 코딩테스트 문법 시리즈 ⑪ : 컬렉션 유틸 함수 정리 (zip, chunked, windowed 등)

2025. 7. 11. 04:02·Code Odyssey

✅ Kotlin은 컬렉션을 효율적으로 다룰 수 있는 유틸 함수들을 제공합니다.


🔹 zip — 두 리스트 병합

val names = listOf("Alice", "Bob")
val scores = listOf(90, 80)
val zipped = names.zip(scores)  // [(Alice, 90), (Bob, 80)]
  • 두 컬렉션을 같은 인덱스로 Pair로 묶음
  • 크기가 다르면 짧은 쪽 기준

🔸 순회 방법

for ((name, score) in zipped) {
    println("$name: $score")
}
val names = listOf("Alice", "Bob")
val scores = listOf(90, 80)
val zipped = names.zip(scores)  // [(Alice, 90), (Bob, 80)]
  • 두 컬렉션을 같은 인덱스로 Pair로 묶음
  • 크기가 다르면 짧은 쪽 기준

🔸 unzip — 분리

val (names2, scores2) = zipped.unzip()

🔸 zipWithNext

val list = listOf(1, 4, 9)
val diff = list.zipWithNext { a, b -> b - a }  // [3, 5]
  • 연속된 두 값을 묶어 처리할 때 유용함

🔹 flatMap — 2차원 리스트 평탄화 및 변환

val nested = listOf(listOf(1, 2), listOf(3, 4))
val flat = nested.flatMap { it }  // [1, 2, 3, 4]
  • map + flatten을 동시에 수행
  • 중첩 리스트 구조를 1차원으로 펼침
val transformed = nested.flatMap { it.map { n -> n * 2 } }  // [2, 4, 6, 8]

🔸 flatten vs flatMap

val nested = listOf(listOf(1, 2), listOf(3, 4))
nested.flatten()              // [1, 2, 3, 4]
nested.flatMap { it }         // 동일 결과
nested.flatMap { it.map { x -> x * 2 } }  // [2, 4, 6, 8]
  • flatten() : 중첩 리스트(List)를 1차원(List)으로 변환 (요소 변환 없이 단순 펼침)
  • flatMap() : 중첩 리스트를 펼치면서 내부 요소에 변환(map)을 적용 (map + flatten의 역할)

🔹 chunked — 고정 크기로 잘라서 리스트로

val list = (1..10).toList()
val chunked = list.chunked(3)  // [[1,2,3], [4,5,6], [7,8,9], [10]]
  • 주어진 크기 단위로 쪼갬
  • 마지막은 남은 크기만큼 포함

🔹 windowed — 슬라이딩 윈도우 처리

val list = (1..10).toList()

val win1 = list.windowed(size = 3, step = 1, partialWindows = false)
// [[1,2,3], [2,3,4], [3,4,5], ..., [8,9,10]]

val win2 = list.windowed(size = 3, step = 2, partialWindows = false)
// [[1,2,3], [3,4,5], [5,6,7], [7,8,9]] ← 10은 포함되지 않음

val win3 = list.windowed(size = 3, step = 2, partialWindows = true)
// [[1,2,3], [3,4,5], [5,6,7], [7,8,9], [9,10]] ← 끝부분 포함
  • size: 윈도우 크기
  • step: 슬라이딩 간격
  • partialWindows: 끝부분 남은 것도 포함할지 여부
    • false → 마지막 청크가 부족하면 제외
    • true → 남은 요소라도 포함

🔹 withIndex — 인덱스와 함께 순회

for ((i, v) in list.withIndex()) {
    println("index=$i value=$v")
}
  • enumerate() 느낌으로 자주 사용됨

🔹 groupingBy - 그룹핑 후 빈도수/누적값 집계

HashMap 없이도 빈도수 집계에 매우 유용

  • groupingBy { 키 추출 }로 그룹핑 기준 지정
  • 단독 사용x groupingBy는 Grouping<T, K> 반환

🔸 groupingBy{it}.eachCount() – 그룹별 개수 세기

val items = listOf("a", "b", "a", "c", "b", "a")
val counts = items.groupingBy { it }.eachCount()
println(counts)  // {a=3, b=2, c=1}
  • eachCount()로 그룹별 개수 계산 (빈도수 구하기)
  • 실전 코테에서 문자 등장 횟수 세기 등에 매우 자주 등장

🔸 groupingBy{it}.fold(initial) {operation} – 그룹별 누적 처리 (합계, 리스트 등)

val data = listOf("a", "ab", "abc", "b", "bc")
val lengthsByFirstChar = data.groupingBy { it.first() }.fold(0) { acc, str -> acc + str.length }
// {a=6, b=4}
  • 'a' 그룹: "a"(1) + "ab"(2) + "abc"(3) → 총 길이 6
  • 'b' 그룹: "b"(1) + "bc"(2) → 총 길이 3
  • fold(initial) { acc, element -> ... }로 누적 처리
  • 실전에서는 그룹별 점수 합산, 값 리스트화 등에 사용 가능

🔸 groupBy vs groupingBy

  • groupBy는 Map<K, List>를 반환
  • groupingBy는 중간 리스트를 만들지 않고 직접 집계함
    → 메모리 효율성 ↑

✅ 고차 함수(시리즈 ⑩)와 컬렉션 유틸 함수(시리즈 ⑪) 차이

구분 고차 함수의 예 (람다 기반) 구조 기반 컬렉션 유틸 함수 비고
핵심 개념 람다를 인자로 받아 조건 검사 또는 변환 수행 구조적으로 컬렉션을 병합·분할·슬라이딩 등 조작 일부 함수는 둘 다 해당
대표 함수 map, filter, any, all, groupBy 등 zip, chunked, windowed, flatten, partition 등 flatMap은 둘 다 포함됨
목적 조건에 따라 요소를 필터링·변환하거나, Boolean/Map 등으로 결과 도출 컬렉션 구조 자체를 재구성 (쌍 만들기, 구간 분할 등) 목적에 따라 쓰임이 다름
사용 예 성적 90점 이상 필터링, 문자열 길이 추출 등 두 리스트 병합, 3개씩 자르기, 슬라이딩 윈도우 처리 등 반복적 데이터 처리에 적합

✅ 요약 정리

함수 설명
zip 두 리스트를 Pair로 병합 (a[i] to b[i])
unzip Pair 리스트를 두 리스트로 분리
zipWithNext 인접한 요소끼리 묶기 ([a,b,c] → [(a,b), (b,c)])
flatMap 중첩 리스트를 평탄화하며 변환 (List<List<T>> → List<T>)
chunked(n) 고정 크기 청크로 나눔 (["ab", "cd", "ef"])
windowed(size, step) 슬라이딩 윈도우 구간 추출
withIndex 인덱스와 함께 순회 (for ((i, v) in list.withIndex()))
groupingBy 그룹핑 후 빈도수/누적값 집계 (.eachCount(), .fold())

다음은 시리즈 ⑫: 누적 함수 (reduce, fold, scan 등) 으로 이어집니다.

'Code Odyssey' 카테고리의 다른 글

Kotlin 코딩테스트 문법 시리즈 ⑬ : Scope Function 정리 (let, also, apply, run, takeIf)  (0) 2025.07.13
Kotlin 코딩테스트 문법 시리즈 ⑫ : 누적 함수 정리 (reduce, fold, scan)  (1) 2025.07.12
Kotlin 코딩테스트 문법 시리즈 ⑩ : 고차 함수 정리 (map, filter, any 등)  (1) 2025.07.10
Kotlin 코딩테스트 문법 시리즈 ⑨ : 정렬 (기본, 조건, 다중 기준)  (1) 2025.07.09
Kotlin 코딩테스트 문법 시리즈 ⑧ : 스택 / 큐 / 우선순위 큐 정리  (0) 2025.07.08
'Code Odyssey' 카테고리의 다른 글
  • Kotlin 코딩테스트 문법 시리즈 ⑬ : Scope Function 정리 (let, also, apply, run, takeIf)
  • Kotlin 코딩테스트 문법 시리즈 ⑫ : 누적 함수 정리 (reduce, fold, scan)
  • Kotlin 코딩테스트 문법 시리즈 ⑩ : 고차 함수 정리 (map, filter, any 등)
  • Kotlin 코딩테스트 문법 시리즈 ⑨ : 정렬 (기본, 조건, 다중 기준)
Celion
Celion
오늘도 평소처럼 화이팅!
  • Celion
    Orion Log
    Celion
  • 전체
    오늘
    어제
    • 전체 글 (144)
      • Uncompiled Thoughts (8)
        • 네이버 부스트캠프 10기 (5)
      • CS 기초부터 한 걸음씩 (34)
      • Code Odyssey (22)
      • Algorithm (77)
        • Coding Test Records (63)
      • Git (3)
      • reference (0)
  • 블로그 메뉴

    • 태그
    • 방명록
  • 태그

    알고리즘고득점kit
    Level3
    백준
    시뮬레이션
    java
    프로그래머스
    코테
    문법정리
    Kotlin
    boostcamp
    Level2
    greedy
  • 최근 글

  • 인기 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.4
Celion
Kotlin 코딩테스트 문법 시리즈 ⑪ : 컬렉션 유틸 함수 정리 (zip, chunked, windowed 등)
상단으로

티스토리툴바