/ KOTLIN

kotlin collection.associateBy,groupBy,partition

코틀린에서는 Guava 다른 여타 편라한 기능을 제공하던 라이브러리를 사용하지않고도 충분히 많은 일을 효율적이고 간편하게 해결 할 수 있도록 제공하고있습니다. 귀찮은 문제를 가볍게 해결 해주는 편리한 함수 associateBy, groupBy에 대해 정리해보겠습니다.

associateBy

Returns a Map containing the values provided by valueTransform and indexed by keySelector functions applied to elements of the given array.
If any two elements would have the same key returned by keySelector the last one gets added to the map.
The returned map preserves the entry iteration order of the original array.

valueTransform에서 제공하고 주어진 배열의 요소에 적용된 keySelector 함수에 의해 인덱싱 된 값을 포함하는 Map을 반환합니다. 두 요소가 keySelector에 의해 반환 된 동일한 키를 갖는 경우 마지막 요소가 맵에 추가됩니다. 반환 된 맵은 원래 배열의 항목 반복 순서를 유지합니다.

public inline fun <T, K, V> kotlin.Array<out T>.associate(transform: (T) -> kotlin.Pair<K, V>): kotlin.collections.Map<K, V> { /* compiled code */ }

실제 구현부 중에 Array의 형태를 보면 transform을 통해 Key/Value형태로 다시 Map을 반환하는 것을 확인 할 수 있습니다.

val charCodes = intArrayOf(72, 69, 76, 76, 79)

val byChar = charCodes.associateBy { it.toChar() }

// L=76 only occurs once because only the last pair with the same key gets added
println(byChar) // {H=72, E=69, L=76, O=79}
{H=72, E=69, L=76, O=79}

이 예제에서 중요한 것은 두개의 76중 어떤 값이 실제 저장된걸까?입니다. 정답은 뒤에 들어온 76입니다. 아래의 예를 보시면 조금 더 명확해집니다.

val articles = listOf(
    Article("갤러리 글", 2, "내용", "이미지"),
    Article("일반글 2", 3, "내용", "일반글"),
    Article("공지입니다.", 4, "내용", "공지"),
    Article("필독 공지입니다.", 1, "내용", "공지"),
    Article("일반글 3", 5, "내용", "일반글")
)
print(articles.associateBy { if (it.type == "공지") "공지" else "그외" })
{
    그외=Article(title=일반글 3, id=5, body=내용, type=일반글), 
    공지=Article(title=필독 공지입니다., id=1, body=내용, type=공지)
}

kotlinlang.org에서 제공하는 예제처럼 collection을 map으로 단순히 반환하는 구현에도 사용가능합니다.

groupBy

가령 서버에서 게시글 목록을 내려주었는데, 게시글 중에 공지사항만 모아서 헤더아이템으로 제공하고 싶은 경우도 associateBy를 활용하면 가능합니다. (정렬은 그냥 넣어봤어요.)

print(articles.sortedBy { it.id }.groupBy { if (it.type == "공지") "공지" else "그외" })
{
    공지 = [Article(title = 필독 공지입니다 ., id = 1, body = 내용, type = 공지),
        Article(title = 공지입니다., id = 4, body = 내용, type = 공지)],
    그외 = [Article(title = 갤러리 , id = 2, body = 내용, type = 이미지),
        Article(title = 일반글 2, id = 3, body = 내용, type = 일반글),
        Article(title = 일반글 3, id = 5, body = 내용, type = 일반글)]
}

partition

하나의 규칙을 통해서 두개의 컬랙션으로 나눈다면 차라리 partition을 쓰는게 더 직관적일 수 있습니다.

print(articles.partition { it.type == "공지" })
(
    [Article(title = 공지입니다., id = 4, body = 내용, type = 공지),
     Article(title = 필독 공지입니다 ., id = 1, body = 내용, type = 공지)],
    [Article(title = 갤러리 , id = 2, body = 내용, type = 이미지),
     Article(title = 일반글 2, id = 3, body = 내용, type = 일반글),
     Article(title = 일반글 3, id = 5, body = 내용, type = 일반글)]
)

Search

Get more post