ArrayList, group by, sumBy нескольким полям
Есть такой код на kotlin...
class ResultGroup(var userId: Int, var movieRating: List<MovieRating>? = null)
class MovieRating(public var movieTitle: String? = null, var rating: Int? = null)
В ResultGroup лежат данные не сгруппированные, т.е. пользователь и фильмы (movieTitle) которые он смотрел с количеством просмотров (rating), все нужно сгруппировать по userId, movieTitle, а rating просуммировать.
Делаю что то вроде:
val a = resultList.groupBy { {ResultGroup::userId};{MovieRating::movieTitle} }
.mapValues { it.value.sumBy { it.movieRating........... } }
ну и т.п. и т.д, кажется все уже перепробовал, но компилятор постоянно ругается, уговорить не удается)) Подскажите как в данном случае правильно это сделать?
Ответы (1 шт):
Автор решения: Темка тоже
→ Ссылка
Как-то так, если я правильно понял вопрос
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
class ResultGroup(val userId: Int, val movieRating: List<MovieRating>)
class MovieRating(val movieTitle: String, val rating: Int)
class Tester {
@Test
fun test() {
val userId1 = 1
val userId2 = 2
val movieTitle1 = "film1"
val movieTitle2 = "film2"
val resultList: List<ResultGroup> = listOf(
ResultGroup(
userId1,
listOf(MovieRating(movieTitle1, 2), MovieRating(movieTitle2, 2))
),
ResultGroup(
userId2,
listOf(MovieRating(movieTitle1, 2))
),
ResultGroup(
userId1,
listOf(MovieRating(movieTitle1, 4))
)
)
// Раскываем всё в сплошной лист
val a = resultList.flatMap { topIt ->
topIt.movieRating.map { downIt ->
Triple(topIt.userId, downIt.movieTitle, downIt.rating)
}
}
//Группируем по паре (пользователь, фильм)
val r = a.groupBy({ Pair(it.first, it.second) }, { it.third })
//Считаем общее количество просмотров для каждой пары (пользователь, фильм)
val uniqueList = r.entries.map {
Triple(it.key.first, it.key.second, it.value.fold(0, { acc, t -> acc + t }))
}.toList()
Assertions.assertEquals(6, uniqueList.find { it.first == userId1 && it.second == movieTitle1 }!!.third)
Assertions.assertEquals(2, uniqueList.find { it.first == userId1 && it.second == movieTitle2 }!!.third)
Assertions.assertEquals(2, uniqueList.find { it.first == userId2 && it.second == movieTitle1 }!!.third)
}
}