将列表分为连续的相同对象列表

时间:2019-10-02 09:41:16

标签: kotlin

说我有一个函数,可以将字符列表收集到所有连续的相同字符的列表中:

 [a, a, b, a, b, b, b, c, c, c, c] -> [[a, a], [b], [a], [b, b, b], [c, c, c, c]]

我在这里的解决方案是像这样手动填充ArrayList:

fun foo(chars: List<Char>): List<List<Char>> {
    val result = arrayListOf<ArrayList<Char>>()
    var part = arrayListOf(chars.first())
    var cur = chars.first()
    for (char in chars.drop(1)){
        if (cur == char) part.add(char)
        else {
            cur = char
            result.add(part)
            part = arrayListOf(char)
        }
    }
    if(part.isNotEmpty()) result.add(part)
    return result
}

但是,这似乎太糟糕了,所以我认为必须有一种更好的方法来做到这一点。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

您可以使用groupBy [功能] [1]:

val chars = listOf('a', 'a', 'b', 'a')

val result = chars.groupBy { it } // Map<Char,List<Char>> = ['a' to ['a','a'], 'b' to ['b']]

如果您之后想要列表列表,只需使用result.values

编辑

感谢指出,答案不应该包括所有的群体,而应该包括相应的群体。解决方案要更长一些:

val chars = listOf('a', 'a', 'b', 'a')

val result = chars.fold(mutableListOf<Char>() to mutableListOf<List<Char>>()) { (currentList, allLists), currentItem ->

    if (currentList.isEmpty()) { // Applies only to the very first item
        mutableListOf(currentItem) to allLists
    } else {

        if (currentItem == currentList.first()) { // same char
            currentList.apply { add(currentItem) } to allLists
        } else {
            mutableListOf(currentItem) to allLists.apply { add(currentList) } // Next
        }

    }
}
    .let { it.second.apply { add(it.first) } } //Convert to List<List<Char>> and add last remaining list

答案 1 :(得分:1)

作为一种选择,可以单行转换

fun main(args: Array<String>) {

    val list = arrayListOf('a', 'a', 'b', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'c')
    val result = "(\\w)\\1*".toRegex().findAll(list.joinToString("")).map { it.value.toCharArray() }.toList()

    for (arr in result) {
        print(arr.contentToString()) // prints [a, a][b][a][b, b, b][c, c, c, c]
    }

}