Как сгруппировать значения с уникальными инкрементальными ключами в Kotlin? - PullRequest
0 голосов
/ 15 января 2019

Например, у меня есть такой список:

{{1,"a"},{2,"a"},{3,"b"},{4,"b"},{5,"b"},{6,"a"},{7,"a"},{8,"a"}}

Если я использую groupBy { it.value } Котлина, то это будет выглядеть так:

{
   a: = {1,2,6,7,8},
   b: = {3,4,5}
}

Но я хочу сгруппировать это так:

{
   a1: = {1,2},
   b1: = {3,4,5},
   a2: = {6,7,8}
}

Какую функцию Котлина я должен использовать?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Учитывая List (поскольку порядок имеет значение) Pair<Int, String>, например:

val list = listOf(1 to "a", 2 to "a", 3 to "b", 4 to "b", 5 to "b", 6 to "a", 7 to "a", 8 to "a")

, вы можете сделать что-то вроде этого:

fun groupCount(list: List<Pair<Int, String>>): Map<String, List<Int>> {
    val countMap = mutableMapOf<String, Int>()
    var currentStr = list.firstOrNull()?.second ?: return emptyMap()

    return list.map { (key, value) ->

        if(currentStr != value) {
            currentStr = value
            countMap[value] = ((countMap[value] ?: 0) + 1)
        }

        key to value + countMap.getOrPut(value, {1})
    }.groupBy ({it.second}, {it.first})
}

В конце концов, у Котлина groupBy становится особенно удобным, когда вам нужно повернуть это

[(1, a1), (2, a1), (3, b1), (4, b1), (5, b1), (6, a2), (7, a2), (8, a2)]

в это:

{a1 = [1,2], b1 = [3, 4, 5], a2 = [6, 7, 8]}


Если у вас есть Map<Int, String>, вы можете позвонить toList()прежде чем передать его на groupCount.

0 голосов
/ 16 января 2019

Ну, это довольно особый вариант использования. Одна, не совсем функциональная, реализация может выглядеть так:

fun subgroups(data: Map<Int, String>): Map<String, List<Int>> {
    if (data.isEmpty()) throw IllegalArgumentException()
    val counter = data.values.toSet().associateWithTo(mutableMapOf()){ 1 }
    var last = data.values.first()
    val result = mutableMapOf<String, List<Int>>()
    data.forEach { k, v ->
        if (v != last) {
            counter[last] = counter.getOrDefault(last, 0) + 1
            last = v
        }

        "$v${counter[v]}".let { key ->
            result[key] = result.getOrDefault(key, listOf()) + k
        }
    }
    return result
}

Я надеюсь, что это работает для вас

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...