Kotlin Aggregate Operation(1) : reduce(), fold()

Bettor·2024년 3월 17일

참고 : https://blog.leocat.kr/notes/2020/03/09/kotlin-reduce-and-fold

Kotlin 컬렉션 안에는 컬렉션 내의 데이터를 모두 모으는 accumulate 함수가 있대요
그 중에 reduce()와 fold()가 있다는데요.
일단은 accumulate에 대해 검색해볼게요 일단은 축적하다라는 뜻이래요.

'kotlin accumulate'를 검색하면 주로 보이는 키워드가 'reduce','fold', 'aggregate operation'인데 자세한건 나중에 다뤄보겠습니다. 밑에 링크는 최상단에 있는 검색 결과이고,
오늘은 이 세개의 키워드 중 'reduce'와 'fold'에 대해 다뤄보겠습니다.

https://www.google.com/search?q=kotlin+accumulate&oq=kotlin+accum&gs_lcrp=EgZjaHJvbWUqBwgAEAAYgAQyBwgAEAAYgAQyBwgBEAAYgAQyBggCEEUYOTIICAMQABgWGB4yCAgEEAAYFhgeqAIAsAIA&sourceid=chrome&ie=UTF-8#ip=1

이 둘의 차이는, 축적화 작업을 할 때,
reduce()는 초기값 없이 첫번째 element로 시작,
fold()는 지정해준 초기값으로 시작한답니다.

예시를 보겠습니다.

val numbers = listOf(1, 7, 2, 6, 3)

val sum = numbers.reduce { total, num -> total + num }
println("reduced: $sum") // reduced: 19, total에다가 num을 더함으로써 계속 축적해주는 느낌인 것 같아요.
val sumFromTen = numbers.fold(10) { total, num -> total + num } // 변수명에 10으로부터 라고 써 있죠? 초기값을 10으로 선언하고, 1 더하고 9까지 더하게 됩니다.
println("folded: $sumFromTen") // folded: 29

Key Point : 초기값이 어떻게 시작하게 되는지, 축적

reduce()는 초기값이 첫뻔재 element로 시작하는데 빈 컬렉션인 경우에는 element가 없으니까 어떻게 해야할까요?

val numbers = emptyList<Int>()

val sumFromTen = numbers.fold(10) { total, num -> total + num }
println("folded: $sumFromTen") // folded: 10
val sum = numbers.reduce { total, num -> total + num }
println("reduced: $sum")

fold()는 정상적으로 출력이 되지만 reduce()는 UnsupportedOperationException이 발생합니다.

결론 : 컬렉션이 비어있을 가능성이 있다면 fold()를 사용해야 한다.

fold()든 reduce()든 초기값이 어떻든 간에 첫번째부터 element가 사용되기 때문에 아래 코드를 유심히 보자.

 val numbers = listOf(5, 2, 10, 4)

    val doubledSum = numbers.reduce { total, num -> total + num * 2 }
    println("reduced: $doubledSum") // reduced: 37 -> 원래는 42가 나와야 한다!!
    val doubledSumFromZero = numbers.fold(0) { total, num -> total + num * 2 }
    println("folded: $doubledSumFromZero") // folded: 42

코드를 보면 fold()도 0으로 시작해서 동일하게 42기 나와야 하는데, reduce는 37을 출력하고 있다.
reduce()의 total은 첫번째 interation이며 첫번째 element로 사용되고, num은 두번째 element로 사용된다.
반면 fold()의 경우 초기값이 첫번째 iteration의 total로 사용되기 때문에 모든 element의 값이 2배가 된다.
쉽게 이야기하면 fold의 경우 초기값이 total이 0인 상태에서 시작해서 element들이 두배가 되어 하나씩 축적되어 들어오지만,
reduce의 경우 초기값이 5로 시작해서 5가 2배가 되지 못한 상태에서 뒤의 값들이 축적되어 5가 모자라다.
첫번째 interation이 reduce는 첫번째 원소로, reduce는 초기값이 0부터 들어온다.

기억하기 : accumulate, aggregate, map, fiter, iteration

0개의 댓글