Kotlin GroupBy 구현과 정리 # List 그룹핑
오늘은 Kotlin의 GroupBy 에 대해서 정리해 보겠습니다.
1. GroupBy API
우선 해당 API의 코드를 가볍게 보고 가도록 하겠습니다.
아래에서 보듯이 GroupBy는 Iterable 타입의 collection 에서,
전달되는 특정한 기준을 Map의 Key값으로 해서,
그에 해당하는 데이터들을 List로 묶어서 Value에 넣어줍니다.
아래에서 실제로 구현해보면서 좀 더 정리해 보도록 하겠습니다.
2. GroupBy 구현
2-1. Data 클래스 와 데이터 작성
GroupBy를 다루기 전에,
사용할 간단한 데이터클래스를 작성해 보겠습니다.
Student라는 클래스는 이름과 점수만 가지고 있습니다.
data class Student(val name: String, val grade: Int)
그리고 이 클래스의 객체들을 다음과 같이 만들어서 list로 만들어 놓았습니다.
8,9,10 점인 학생들이 보이네요.
val students = listOf(
Student("Kim", 8),
Student("Lee", 10),
Student("Park", 9),
Student("Song", 10),
Student("Jung", 9)
)
2-2. List에 groupBy 사용
이제 해당 점수별로 학생들을 묶어서 보려고 합니다.
8점인 학생들, 9점인 학생들, 10점인 학생들 총 몇명인지 보려고 하는 것 이지요.
이 때 필요한 것이 바로 groupBy 입니다.
list 에 groupBy 함수를 실행해주는데, 블록에 기준을 넣어주면 됩니다.
아래에서는, grade라고 정의해 주었습니다.
위의 코드와 같이 groupBy를 실행해 주면, 아래와 같은 구조를 가지게 되는데요.
{
8: [Student(name="Kim", grade = 8)],
9: [
Student(name="Park", grade=9),
Student(name="Jung", grade=9)
],
10: [
Student(name="Lee", grade=10),
Student(name="Song", grade=10)
]
}
아래 코드를 한 번 실행해 보겠습니다.
println(groupedBy[9]);
결과는 다음과 같습니다.
2-3. Pair 타입과 GroupBy 사용
Pair 타입에 사용하게 되면, GroupBy 의 기준을 잡아줄 때,
둘 중 하나를 지정만 해주면 됩니다.
아래는 Pair 타입의 리스트에서,
groupBy를 Long값을 기준으로 해 주었습니다.
val pairsList: List<Pair<Int, Long>> = listOf(
Pair(1, 10L),
Pair(2, 20L),
Pair(3, 10L),
Pair(4, 30L),
Pair(5, 20L),
Pair(6, 10L)
)
val transformedPairs = pairsList.map { (someInt, someLong) ->
Pair(someInt, someLong)
}
val groupedPairs = transformedPairs.groupBy { (_, someLong) -> someLong }
println(groupedPairs)
결과는 다음과 같습니다.
2-4. GroupBy Value Iteratation
Value에는 list값이 담기게 되므로, iterate을 할 수 있겠지요.
아래 코드로 9점에 해당하는 학생들에 대해서 반복문으로 객체를 출력하도록 할 수 있습니다.
val groupedBy = students.groupBy {
it.grade
}
val nineGrade = groupedBy[9]
nineGrade?.forEach { student ->
println(student.name)
}
결과는 다음과 같습니다.
2-5. 실제사례 정리
조금 복잡해 보이지만, 간단히 보고 가면 좋은데요.
아래에서는,
먼저 네트워크를 통해서 받은 데이터를 flatMapLatest로 가지고 옵니다.
이 데이터에 map연산자를 통해서,
groupBy를 이용해, 데이터를 testKey를 기준으로 Map으로 만들어 줍니다.
이후에, UI에 표현하기 쉽게 하기 위해서, List로 만들어 주는데요.
이 List는 Pair(testKey, valueList)로 만들어주어서 넘겨주면 됩니다.
userId
.flatMapLatest { userId ->
testRepository.fetchsData(userId)
}.map { testData ->
val groupedBy = testData.groupBy { it.testKey }
groupedBy.map { entry ->
Pair(entry.key, entry.value)
}
}