Kotlin映射不能与String列表一起工作



我一直在编写代码,我必须生成所有可能的方法到目标字符串。我正在使用下面提到的代码。

Print语句:

println("---------- How Construct -------")
println("${
window.howConstruct("purple", listOf(
"purp",
"p",
"ur",
"le",
"purpl"
))
}")

函数调用:

fun howConstruct(
target: String,
wordBank: List<String>,
): List<List<String>> {
if (target.isEmpty()) return emptyList()
var result = emptyList<List<String>>()
for (word in wordBank) {
if (target.indexOf(word) == 0) {    // Starting with prefix
val substring = target.substring(word.length)
val suffixWays = howConstruct(substring, wordBank)
val targetWays = suffixWays.map { way ->
val a = way.toMutableList().apply {
add(word)
}
a.toList()
}
result = targetWays
}
}
return result
}

预期输出:-[[‘小狗’,‘乐’],[‘p’,‘你’,‘p’,‘乐’]]

当前输出:-[]

你的代码几乎可以工作了;只需要做一些小的修改就可以得到所需的输出:

  • 如果目标为空,则返回listOf(emptyList()),而不是emptyList()
  • add(0, word)代替add(word)

第一个变化很重要。你的函数返回一个匹配列表;因为每个匹配本身是一个字符串列表,它返回一个字符串列表的列表。一旦你的代码匹配了整个目标并最后一次调用自己,它返回一个空列表——即没有匹配——而不是一个包含空列表的列表——这意味着只有一个匹配,没有剩余的字符串。

第二个更改只是修复了每个匹配中的字符串顺序,这是相反的(因为它在返回的后缀匹配之后附加了前缀)。


然而,还有许多其他方法可以改进代码。与其单独列出它们,不如给出一个替代版本:

fun howConstruct(target: String, wordBank: List<String>
): List<List<String>>
= if (target == "") listOf(emptyList())
else wordBank.filter{ target.endsWith(it) } // Look for suffixes of the target in the word bank
.flatMap { suffix: String ->
howConstruct(target.removeSuffix(suffix), wordBank) // For each, recurse to search the rest
.map{ it + suffix } } // And append the suffix to each match.

这几乎与您的代码完全相同,除了它从字符串的末尾搜索(匹配后缀)而不是从开头搜索。结果是一样的;主要的好处是,将后缀字符串附加到部分匹配列表(使用+)比添加前缀(您会发现,这相当混乱)更简单。

然而,它要简洁得多,主要是因为它使用了函数式风格——特别是,它使用filter()来确定哪些单词是有效后缀,使用flatMap()来递归地整理对应于每个单词的匹配列表,以及使用map()向每个单词添加后缀(就像您的代码一样)。这样就避免了循环遍历列表、创建列表和添加列表的所有工作。因此,它不需要处理可变列表或变量,从而避免了一些混乱和错误的来源。

为了简单起见,我把它写成一个表达式体(用=代替{ … })。我发现这对于短函数来说更简单、更清晰——尽管这是一个极限。它可能适合作为String的扩展函数,因为它有效地返回字符串的转换,没有任何副作用——尽管这往往最适合于短函数。

还有一些小的调整。使用startsWith()endsWith()代替indexOf()更简单,也更有效;removePrefix()removeSuffix()可能比substring()更清晰;我发现== ""isEmpty()更清晰。

(另外,howConstruct()这个名字并不能很好地描述结果,但到目前为止我还没有想出更好的名字…)

这些变化当然是个人喜好的问题,我相信其他开发人员会以许多其他方式编写它!但我希望这能给你一些启发。

相关内容