如何在Kotlin中使用唯一的增量键对值进行分组?

wz3gfoph  于 2023-06-06  发布在  Kotlin
关注(0)|答案(3)|浏览(194)

例如,我有这样的列表:

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

如果我使用Kotlin的groupBy { it.value },那么它会像这样:

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

但我想这样分组:

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

我应该使用什么Kotlin函数?

4ktjp1zp

4ktjp1zp1#

给定Pair<Int, String>List(因为顺序很重要),如下所示:

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})
}

最后,当你需要将这个
[(1,a1),(2,a1),(3,b1),(4,b1),(5,b1),(6,a2),(7,a2),(8,a2)]
变成这样:
{a1=[1,2],bl =[3,4,5],a2=[6,7,8]}
如果你碰巧有一个Map<Int, String>,你可以在把它传递给groupCount之前调用toList()

8e2ybdfx

8e2ybdfx2#

我想这是一个非常特殊的用例。一个不太实用的实现可能看起来像这样:

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
}

希望这对你有用

xytpbqjk

xytpbqjk3#

val result = input
  .fold(
    mutableListOf<Pair<String, MutableList<Int>>>() to mutableMapOf<String, Int>()
  ) { acc, pair ->
    val result = acc.first
    val counters = acc.second
    val number = pair.first
    val letter = pair.second
    if (result.lastOrNull()?.first == letter + counters[letter]) {
      result.last().second.add(number)
    } else {
      result.add(letter + (counters.getOrElse(letter) { 0 } + 1).also { counters[letter] = it } to mutableListOf(number))
    }
    acc
  }
  .first
  .toMap()

相关问题