코틀린 filter, find, groupBy, groupingBy, reduce, fold 사용 예제

2024. 5. 8. 14:09Development/[Kotlin] 코틀린

728x90

우선, 가장 손쉽게 리스트를 하나를 생성한다.

리스트는 문자로 구성된 리스트로 구성한다.

var list = listOf("1", "1", "2", "3")
//[1, 1, 2, 3]

 

filter
list.filter { it == "1" }
// [1, 1]

list.filter { it == "2" }
// [2]

위와 같이 filter 함수에 "조건"을 걸면 조건에 해당하는 값들을 모두 리스트로 반환한다

it == "1" 이라는 조건에서 it는 list 의 항목 값을 뜻하는 일종의 예시 변수명으로 이름은 다음과 같이 원하는 이름으로 바꿀 수 있다.

list.filter { filterId -> filterId == "1" }
//it라는 이름을 filterId 라는 원하는 변수명으로 변경

 

find
list.find { it == "1" }
//1

find 의 경우 조건에 해당하는 값을 1개만 반환한다 (filter 함수와 다르다) 

 

groupBy
val groupBy = list.groupBy { it }
//{1=[1, 1], 2=[2], 3=[3]}

 

groupBy는 조건이 같은 값을 묶어서 Map 형태로 반환하는데,

이때 조건이 단순히 "같은 값만" 묶는 식으로 하면 맵의 키가 1, 2, 3 과 같이 지정되고 이 조건에 해당하는 값들이 리스트로 들어있다

val groupByPair = list.groupBy { it == "1" }
//{true=[1, 1], false=[2, 3]}

조건을 좀 더 걸면 그 조건의 참에 해당하는 값들은 true 키에, 조건의 거짓에 해당하는 값들은 false 키로 분류되며,

각 해당하는 값들이 리스트로 들어있다.

 

반응형

 

이번에는 리스트를 단순 문자 리스트가 아니라 map 을 리스트로 가지는 리스트를 다음과 같이 만들어보자.

var map = listOf("1" to "123", "2" to "bcd", "3" to "123")

*. 코틀린의 경우 위와 같이 아주 편하게 map 형태를 "키 to 값" 과 같이 명시하여 만들수 있다.

map.groupBy { it.first }
//{1=[(1, 123)], 2=[(2, bcd)], 3=[(3, 123)]}

groupBy 함수를 map을 가지는 리스트에 적용하는 경우 위와 같이 출력할 수 있는데,

우선 it. first 에서 first 의 의미를 알기 위해서는 map 을 어떻게 반환하는지 알아야 한다.

map 의 경우 키와 값의 "쌍"으로 이루어져있는데 groupBy가 map의 키,값 쌍을

코틀린의 "Pair" 라는 클래스로 반환한다.

더보기

Pair 클래스에 대해서

public final data class Pair<out A, out B>(
    val first: A,
    val second: B
) : Serializable /* = Serializable */

Pair 클래스는 변수를 2개 가지고 있는데 이때 first에 해당하는 것이 map의 키, second에 해당하는 것이 map의 값이다.

따라서 it. first 는 map의 "키"를 기준으로 groupBy하라는 의미가 되며,

키가 "1", "2", "3" 이기때문에 결과가 {1=[(1, 123)], 2=[(2, bcd)], 3=[(3, 123)]} 으로 반환된다.

호오오옥시나 다음과 같이 만들면 어떻게 될까?

var map중복키 = listOf("1" to "123", "1" to "456", "2" to "bcd", "3" to "123")
map중복키.groupBy { it.first }
//과연?

결과는 

{1=[(1, 123), (1, 456)], 2=[(2, bcd)], 3=[(3, 123)]}

과 같이 출력된다.

같은 키인 "1"을 가진 것이

"1" to "123", "1" to "456"

이렇게 2개이기때문이다.

*. 호오오오옥시나 어? Map은 키가 중복이 안되는거 아닌가? 라고 생각한다면, 위의 "map중복키" 라는 변수명에 속아서(?) 오해를 하면 안된다. 위의 변수는 "단순 리스트"이으로 중복값이 당연히 허용된다.

 

이번에는 그럼 "값"으로 조건을 먹여보면

map.groupBy { it.second }
//{123=[(1, 123), (3, 123)], bcd=[(2, bcd)]}

값이 같은 항목들끼리 묶여있는데, 이때는 키가 first로 조건을 걸었을때와 달리 "값"이 곧 키가 된다.

이번에는 다른 조건을 걸어보기 위해 값을 "숫자"로 갖는 리스트를 만들어서 조건을 걸어보자.

var mapInteger = listOf("1" to 2, "2" to 4, "3" to 1)
mapInteger.groupBy { it.second % 2 == 0 }
//{true=[(1, 2), (2, 4)], false=[(3, 1)]}

그럼 위와 같이 groupBy에 수식을 통해 해당 조건이 참과 거짓인 map이 각각 반환이 된다.

키는 true, false로 나뉜다.

 

groupingBy
var mapInteger = listOf("1" to 2, "2" to 4, "3" to 1)

val groupByValue = mapInteger.groupBy {
    if(it.second % 2 == 0) {
        "짝수"
    }
    else {
        "홀수"
    }
}
//{짝수=[(1, 2), (2, 4)], 홀수=[(3, 1)]}
val groupingByValue = mapInteger.groupingBy {
    if(it.second % 2 == 0) {
        "짝수"
    }
    else {
        "홀수"
    }
}
val counts = groupingByValue.eachCount()
//counts = [짝수=2, 홀수=1]

groupingBy는 조건식을 통해서 조건에 해당하는 값의 갯수를 확인할 수 있는 eachCount 함수를 제공한다.

groupBy와 다른점은 반환 값이 다르기때문에 용도에 따라 다르게 사용이 가능하다

 

다음 글에서는 reduce와 fold에 대해 알아보고자 한다.

var listInteger = listOf(1, 2, 3, 4, 5)

val sumTotal = listInteger.reduce { total, num -> total + num }
// sumTotal == 15 

val sumTotalStart2 = listInteger.fold(2) { total, num -> total + num }
//sumTotalStart2 == 17
728x90
반응형