Nuke Olaf - Log Store

[Kotlin] 표준 라이브러리 - kotlin.collections/ map, filter 본문

Language/[Kotlin]

[Kotlin] 표준 라이브러리 - kotlin.collections/ map, filter

NukeOlaf 2020. 5. 10. 02:52

Kotlin Standard Library 는 collection 에서 유용하게 사용할 수 있는 기능들을 제공한다.

오늘은 그중에서 map 과 filter 에 대해 공부해보았다.

 

1. map

kotlin-stdlib/kotlin.collections/map

map 은 원소를 원하는 형태로 변환한 List 를 반환한다.

Returns a list containing the results of applying the given transform function to each element in the original array.

val numbers = listOf(1, 2, 3)
println(numbers.map { it * it }) // [1, 4, 9]

 

* map 응용

data class Movie(
    val title: String, // 영화 제목 
    val actor: String // 영화 출연진
)

이런 형태의 영화 데이터를 저장하는 data class 가 있다고 생각해보자.

그런데, Movie 데이터의 title 프로퍼티가 html 형식으로 들어와서 String 형식으로 바꿔줘야 한다.
또한, 출연진 String 이
"김아무개|김수한무" 이런 형식으로 되어있어서
"출연진 : 김아무개, 김수한무" 이런 형식으로 바꿔주려고 한다.

map 을 사용하지 않는 기존 방식이라면, 아래와 같이 for 문을 사용할 것이다..

fun processMovie(movies: List<Movie>): List<Movie> {
    for (movie in movies) {
        movie.apply {
            title = Html.fromHtml(title, Html.FROM_HTML_MODE_LEGACY).toString()
            actor = actor.split("|")
                         .joinToString(
                            prefix = "출연진 : ",
                            separator = ", "
                         )
        }           
    }
    return movies
}

 

하지만, map 을 사용하면 아래와 같이 표현할 수 있다.

fun processMovie(movies: List<Movie>): List<Movie> {
    return movies.map {
        it.copy(
            title = Html.fromHtml(title, Html.FROM_HTML_MODE_LEGACY).toString()
            actor = actor.split("|")
                         .joinToString(
                            prefix = "출연진 : ",
                            separator = ", "
                         )
        )
    }
}

 

 

 

2. filter

kotlin-stdlib/kotlin.collections/filter

filter 는 predicate형태의 람다식을 인자로 받아 조건에 따라 collection의 원소를 filtering 한다.

predicate 는 "서술" 이라는 뜻으로, 여기서는 collection 의 원소를 인자로 받아 서술된 조건을 만족하는지 참/거짓 여부를 Boolean 으로 리턴하는 람다를 뜻한다.

Returns a list containing only elements matching the given predicate(lambda functions that take a collection element and return a boolean value). 참고

val numbers: List<Int> = listOf(1, 2, 3, 4, 5, 6, 7)
val evenNumbers = numbers.filter { it % 2 == 0 }
val notMultiplesOf3 = numbers.filterNot { number -> number % 3 == 0 }

println(evenNumbers) // [2, 4, 6]
println(notMultiplesOf3) // [1, 2, 4, 5, 7]

 

* filter 응용

data class Person(
    val name: String,
    val age: Int
)

나이가 30살 이상인 사람의 이름을 출력하는 코드를 작성해보자

val people = listOf(Person("olaf", 24), Person("oshy", 26), Person("void", 30))
val overThirty = people.filter { it.age > 29 }

println(overThirty) // [Person(name=void, age=30)]

 

나이가 가장 많은 사람의 이름을 출력해야한다면 두 가지 방식으로 코드를 작성할 수 있다.

val people = listOf(Person("olaf", 24), Person("oshy", 26), Person("void", 30))

// filter 내부에서 maxBy 사용 (비 권장)
val oldest = people.filter { it.age == people.maxBy{Person::age}!!.age }

// filter 외부에서 maxBy 사용
val maxAge = people.maxBy{Person::age}!!.age
val oldest = people.filter { it.age == maxAge }

println(oldest) // [Person(name=void, age=30)]

Person::age 는 it.age 와 같은 뜻이다

filter 내부에서 maxBy 를 사용한 코드의 경우 filter 를 돌면서 max 를 구하기 위해 또 내부적으로 for 문을 돌게 되기 때문에 매우 비효율적인 코드이다.

코드량을 무작정 줄이기보다는 반복이 중첩되지 않는지 내부적인 동작에 대해 고려하여 작성하는것이 좋다.

 

참고 사이트 >>>

https://tourspace.tistory.com/111

Comments