티스토리 뷰

프로그래밍언어/Kotlin

Kotlin 컬렉션 타입

데니 Denny 2019. 8. 30. 21:18
반응형
SMALL

코틀린에서 제공하는 컬렉션 타입을 이용하면서 iterator(), filter(), map(), forEach() 함수 등을 이용하여 더 간편하게 데이터를 제어할 수 있습니다. 이런 컬렉션 타입의 함수들은 고차 함수로 구현되어 있습니다.

 

1. 집합 연산 함수

forEach() / forEachIndexed()

이 함수는 컬렉션 타입의 데이터 개수 만큼 단순하게 특정 구문을 반복적으로 실행 할 수 있는 함수입니다.

val result = list.filter { it > 10 }

for(i in result) {
    println(i)
}

기존에 위와 같이 코드를 작성했다고 한다면,

val result = list.filter { it > 10 }
                 .forEach { println(it) }

이렇게 사용할 수 있습니다. 위의 코드와 아래 코드는 동일한 결과를 나타내주는 코드입니다.

 

forEachIndexed() 함수는 forEach()와 동일하나 람다식에 인덱스 값까지 넘겨 줄 수 있는 함수입니다.

예시 코드를 살펴보도록 하겠습니다.

listOf(1, 2, 3)
    .forEachIndexed { index, value -> println("index : $index, value : $value") }

실행 결과

all(), any()

all() 함수는 컬렉션 타입의 데이터가 특정 조건에 모두 만족하는지 판단할 때 사용하며, any() 함수는 특정 조건에 만족하는 데이터가 있는지 판단할 때 사용하는 함수입니다.

class User(val name: String, val age: Int)
var list = listOf(User("kim", 25), User("lee", 20))

println("all() : ${list.all { it.age > 22 }}")
println("any() : ${list.any { it.age > 22 }}")

실행 결과

count(), find()

count() 함수는 람다식으로 대입한 조건에 만족하는 데이터의 개수를 반환하는 함수이며 find() 함수는 조건에 만족하는 가장 첫 번째 데이터를 반환하는 함수입니다.

var list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)

println("count() : ${list.count { it > 6 }}")
println("any() : ${list.find { it > 6 }}")

실행 결과

reduce(), reduceRight(), fold(), foldRight()

reduce() 와 fold() 함수는 이 함수에 람다 함수를 대입하게 되면 컬렉션 타입의 데이터를 람다 함수에 차례로 전달한 후 람다 함수의 결괏값을 반환해주는 함수입니다. 특징이라면 람다 함수에서 반환한 값을 기억하고 있다가 그 다음 데이터에 의해 호출 될 때 이전에 반환했던 값을 함께 전달해 주어 참조가 가능하도록 해주는 특징을 가지고 있습니다.

 

reduce()와 fold()의 차이점은 초기값의 지정여부에 있습니다.

fold() 함수는 초기값을 지정할 수 있으며 reduce() 함수는 초기값을 지정할 수 없습니다.

var result = listOf(1, 2).fold(10, { total, next -> 
    println("$total ... $next")
    total + next
})
println("fold test : $result")

실행 결과

위 함수를 살펴보면 먼저 fold 함수의 초기값으로 10이 들어갑니다.

그러면 total에 10이 저장되고 next에는 listOf(1, 2)의 첫 번째 값인 1이 들어갑니다. 그 후 total + next를 한 값 즉, 11이 다음 fold의 total에 저장이 되고 listOf(1, 2)의 두 번째 값인 2가 next에 들어가며 11+2 = 13이 최종적으로 result에 반환됩니다.

val result = listOf(1, 9, 2, 7).fold(0, { max, next ->
    if ( max < next ) next else max
})
println("fold-max value is $result.")

실행 결과

위와 같이 fold 함수를 사용하면 간단하게 최대 값을 구하는 코드를 작성할 수 있습니다.

foldRight() 함수는 왼쪽부터 데이터가 들어갔던 fold()와 반대로 오른쪽부터 왼쪽으로 데이터가 들어가게 됩니다.

 

reduce()함수도 fold()함수와 같지만 초기값이 없습니다. 만약 람다 함수에 대입되는 컬렉션 타입의 변수가 비어있다면 Runtime 시에 에러가 발생하게 됩니다. 이럴 경우에는 fold를 사용해야 합니다.

 

max(), maxBy(), min(), minBy()

위 함수는 최대 값과 최소 값을 반환해주는 함수입니다. By가 있고 없고의 차이는 개발자가 직접 정의한 람다 함수를 넣어줄 수 없다는 것이 특징입니다.

var result: Int? = listOf(1, 11, 3, 7).max()
println("max text : $result")
var result: Int? = listOf(1, 11, 3, 7).maxBy { it % 10 }
println("max text : $result")

코드를 보면 알 수 있듯이 개발자가 직접 정의한 로직을 작성한 람다 함수를 대입할 수 없다는 것이 max와 maxBy의 큰 차이입니다.

min도 max와 동일합니다.

 

none(), sumBy()

none() 함수는 람다 함수에서 지정한 조건을 만족하는 데이터가 없으면 true, 있으면 false를 반환합니다.

sumBy() 함수는 람다 함수를 거쳐서 반환한 모든 값을 더하는 함수입니다. 

예를 들어 10으로 나눈 나머지가 0인 정수들의 합을 구하고 싶다면 다음과 같이 해볼 수 있을 것 같습니다.

val numList = listOf(11, 20, 30, 41, 50)
val result = numList.filter{it % 10 == 0}.sumBy{ it }
println("result : $result")

 

2. 필터링 함수

filter()

filter() 함수는 컬렉션 타입의 데이터 중 특정 조건에 만족한 데이터들을 반환해주는 함수입니다. 굉장히 많이 사용하는 함수입니다. 바로 위에서도 사용했고 가장 위에서 forEach부분에서도 사용한 바가 있습니다.

그럼 여기서는 Map 타입의 객체에서 filter를 사용하는 예시를 살펴보도록 하겠습니다.

val map = mapOf<String, Int>("one" to 15, "two" to 5)
val result = map.filter { entry -> entry.value > 10 }.forEach{ println(it) }

출력 값은 one=15 가 됩니다.

 

filterrNot(), filterNotNull()

filter()를 가장 많이 사용하지만 어쩌다가 종종 사용하는 함수들입니다. filterNot() 함수는 filter()와는 반대의 기능을 하는 함수입니다. 즉, 조건에 맞지 않은 값들만 반환하는 함수이며 filterNotNull() 함수는 null이 아닌 변수만 반환해주는 함수입니다.

 

drop(), dropWhile(), dropLastWhile()

위 함수는 컬렉션 데이터 중 일부분을 제외하고 나머지를 추출할 때 사용합니다. 

drop() 함수는 매개변수로서 숫자를 대입하면 대입된 숫자의 개수(2를 대입하면 앞에서부터 2개의 데이터)를 제외한 나머지 데이터들을 출력할 수 있게 됩니다.

val result = listOf(1, 2, 3, 4, 5).drop(2)
println("result : $result")

dropWhile() 함수는 매개변수로써 람다 함수를 지정하고 앞부분부터 조건에 만족하지 않는 데이터가 나올 때 데이터를 제외하는 함수입니다. 조건에 만족하지 않는 데이터가 나오는 순간 그 데이터로부터 나머지 데이터들을 추출합니다.

val result = listOf(2, 1, 12, 5, 23).dropWhile { it < 10 }
println("result : $result").  // Result : [12, 5, 23]

dropLastWhile() 함수는 dropWhile() 함수와 탐색 방향에 있어 반대방향입니다.

dropWhile() 함수가 앞부분부터 탐색했다고 한다면 dropLastWhile() 함수는 뒤에서부터 데이터를 탐색합니다.

 

slide(), take(), takeLast(), takeWhile()

위 함수들은 특정 위치에 있는 데이터를 추출하는 함수입니다.

slide() 함수는 범위나 숫자 값을 여러 개 대입하고 그 위치에 있는 데이터만 추출(반환)합니다.

listOf(1, 12, 5, 23, 5, 4).slice(1 .. 3).forEach { println(it) }
// 12, 5, 23

인덱스가 0, 1, 2, 3, 4, 5이므로 인덱스 1부터 3까지 즉, 2번째 부터 4번째 까지 12, 5, 23이 출력됩니다.

 

take() 함수는 숫자 값을 매개변수로 전달하며 앞의 값부터 매개 변수로 넣어준 숫자 만큼의 개수의 데이터를 반환합니다.

listOf(1, 12, 5, 23, 5, 4).take(3).forEach { println(it) }
// 1, 12, 5

앞에서부터 3개 즉, 1, 12, 5가 출력됩니다.

 

takeLast()는 take()와 반대이며, takeWhile()은 데이터가 조건에 맞지 않을 때까지 직전의 데이터까지만 출력해주는 함수입니다.

listOf(11, 12, 5, 23, 5, 4).takeWhile { it > 10 }.forEach { println(it) }

it이 10이하가 나오는 순간 탐색을 멈추고 그 직전 값까지 출력하는데 위 코드에서는 11과 12가 출력됩니다.

 

 

이번 포스트에서는 집합 연산 함수와 필터링 함수에 대해 알아보았습니다.

다음 포스트에서는 매핑 함수, 요소 함수, 정렬 함수에 대해 살펴보도록 하겠습니다.

반응형
LIST
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함