微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

惯用的分组字符串计算连续重复的字符

如何解决惯用的分组字符串计算连续重复的字符

我用什么成语可以达到预期的效果

val input = "aaaabbbcca"

val result = input.(here do the transformations)

val output = listof("a" to 4,"b" to 3,"c" to 2,"a" to 1)

assert(result == output)

解决方法

这是一种使用 fold

不变地做到这一点的有趣方法
fun main() {
    val result = "aaaabbbcca"
        .chunked(1)
        .fold(emptyList<Pair<String,Int>>()) { list,current ->
            val (prev,count) = list.lastOrNull() ?: Pair(current,0)
            if (prev == current) list.dropLast(1) + Pair(current,count + 1)
            else list + Pair(current,1)
        }

    val output = listOf("a" to 4,"b" to 3,"c" to 2,"a" to 1)
    check(result == output)
    println(result)
}

输出:

[(a,4),(b,3),(c,2),(a,1)]
,

这是一个棘手的小问题,我找不到特定的惯用解决方案。

然而,这里有一个非常简洁的:

val result = input.replace(Regex("(.)(?!\\1)(.)"),"$1§$2")
                  .split("§")
                  .map{ Pair(it[0],it.length) }

它使用一个复杂的小正则表达式在每对不同的字符之间插入一个标记字符(此处为 §,当然它适用于任何不能在输入中的字符)。 ((?…) 是零宽度前瞻断言,因此 (?!\1) 断言下一个字符与前一个字符不同。 我们需要在匹配中包含下一个字符,否则它将附加最后一个字符后也有一个标记。)

在这种情况下给出 aaaa§bbb§cc§a

然后我们在标记处拆分字符串,给出一个字符组列表(在本例中为 "aaaa","bbb","cc","a"),很容易将其转换为 (character,length) 对。

使用正则表达式并不总是一个好的解决方案,尤其是当它像这样复杂且不直观时。所以这在生产代码中可能不是一个好的选择。另一方面,使用 fold()reduce() 的解决方案可能也不会那么容易阅读。事实上,最可维护的解决方案可能是循环字符的老式解决方案......

,

我相信没有好的(有效的、可读的)惯用方法来解决这个问题。我们可以使用一个很好的、陈旧的、无聊的循环方法。为了让它至少更有趣一点,我们可以使用协程进行惰性计算:

fun String.countConsecutive() = sequence {
    if (isEmpty()) return@sequence
    val it = iterator()
    var curr = it.next()
    var count = 1
    it.forEach {
        if (curr == it) {
            count++
        } else {
            yield(curr.toString() to count)
            curr = it
            count = 1
        }
    }
    yield(curr.toString() to count)
}

如果我们的字符串很长并且我们只需要迭代连续的组,这很好。如果我们不需要迭代所有这些,那就更好了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。