如何用Kotlin.Collections函数将特定格式文本转为Map<String, List<String>>
用Kotlin集合操作优雅实现文本到Map的转换
输入文本示例
[John] likes: cats, dogs dislikes: bananas other info: is a man baby [Amy] likes: theater dislikes: cosplay [Ghost] [Gary] age: 42
转换需求
将上述文本转换为Map<String, List<String>>,规则如下:
- 提取每行中
[Key]格式的内容作为Map的键 - 后续所有非键行(直到下一个键出现)作为对应键的值列表,空行直接忽略
- 没有后续行的键对应空列表
转换后的结构示例:
Key: "John" Value: ["likes: cats, dogs", "dislikes: bananas", "other info: is a man baby"] Key: "Amy" Value: ["likes: theater", "dislikes: cosplay"] Key: "Ghost" Value: [] Key: "Gary" Value: ["age: 42"]
优雅的Kotlin集合操作实现
fun parseTextToMap(text: String): Map<String, List<String>> { // 匹配[Key]格式的正则表达式 val keyPattern = Regex("^\\[(.*)\\]$") return text.lineSequence() // 去除每行前后空白字符 .map { it.trim() } // 过滤掉空行 .filter { it.isNotEmpty() } // 用fold累积中间结果,跟踪当前处理的键和对应的值列表 .fold(mutableListOf<Pair<String, MutableList<String>>>()) { accumulator, line -> keyPattern.matchEntire(line)?.let { matchResult -> // 匹配到新键,添加新的键值对到累积器 accumulator.add(matchResult.groupValues[1] to mutableListOf()) } ?: run { // 非键行,添加到当前最后一个键的值列表中 accumulator.lastOrNull()?.second?.add(line) } accumulator } // 将中间的可变结构转换为不可变的Map .associate { (key, values) -> key to values.toList() } }
代码说明
- 用
lineSequence()懒加载每行文本,处理大文件时更高效 - 全程通过函数式操作链完成转换,没有显式的for循环,代码简洁易读
- 最后转换为不可变的Map和List,符合Kotlin的不可变优先原则
测试示例
fun main() { val input = """ [John] likes: cats, dogs dislikes: bananas other info: is a man baby [Amy] likes: theater dislikes: cosplay [Ghost] [Gary] age: 42 """.trimIndent() val result = parseTextToMap(input) result.forEach { (key, values) -> println("Key: \"$key\"") println("Value: $values\n") } }
运行后输出的结果完全符合需求。
内容的提问来源于stack exchange,提问作者manabreak
相关产品推荐
相关产品推荐

