Kotlin集合操作问题:如何获取多个最长单词中的最后一个
问题描述
我编写了一段Kotlin代码,整体运行正常,但当存在多个长度相同的最长单词时,代码只会返回第一个最长单词,而我需要获取最后一个。例如输入:AWord BWord ALongWord BLongWord CLongWord,当前代码输出A,期望输出C。我认为可以使用reduce函数实现,但不太清楚具体方式,可能需要重构现有实现(maxBy无法满足需求),请帮忙修改代码或提供解决方案。这是一项涉及集合操作的学习任务。
原代码:
fun main(){ val result1 = readLine()?.split(" ")?.associateWith { it.length }?.maxBy { it.value }.let{it?.key?.get(0)}.let { println(it) } }
解决方案
方法一:使用reduce函数实现
reduce可以遍历集合并逐步累积结果,我们可以在遍历过程中设定规则,保留最后一个长度最长的单词:
- 若当前单词长度大于累积的单词,更新累积结果为当前单词
- 若长度相等,同样更新累积结果为当前单词(确保后面的长单词覆盖前面的)
修改后的代码:
fun main() { readLine()?.split(" ")?.takeIf { it.isNotEmpty() }?.reduce { acc, current -> if (current.length >= acc.length) current else acc }?.get(0)?.let { println(it) } }
代码解释
readLine()?.split(" "):读取输入并按空格分割为单词列表takeIf { it.isNotEmpty() }:过滤空列表,避免后续操作抛出异常reduce { acc, current -> ... }:acc代表累积的结果,初始值为列表第一个单词- 每次比较当前单词与累积单词的长度,优先保留长度更长的;长度相同时保留当前单词,最终得到原列表中最后一个最长单词
?.get(0):提取目标单词的首字符?.let { println(it) }:输出最终结果
方法二:反转列表后使用maxByOrNull
如果不想用reduce,也可以通过反转列表,让原列表最后一个最长单词变成反转后列表的第一个最长单词,再用maxByOrNull获取:
fun main() { readLine()?.split(" ")?.reversed()?.maxByOrNull { it.length }?.get(0)?.let { println(it) } }
使用maxByOrNull替代maxBy,可以避免空列表触发异常,代码更安全。
原代码问题分析
原代码中associateWith { it.length }会生成键为单词、值为长度的Map,但maxBy { it.value }只会返回Map中第一个值最大的键值对,因此只能拿到第一个最长单词;此外如果输入中有重复单词,associateWith会覆盖之前的条目,存在潜在逻辑漏洞。
内容的提问来源于stack exchange,提问作者dieforreborn
相关产品推荐
相关产品推荐

