Kotlin 地图不适用于字符串列表
Kotlin map not working with List of String
我一直在编写代码,我必须在其中生成目标字符串的所有可能方式。我正在使用下面提到的代码。
打印报表:
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
}
预期输出:-
[['purp','le'],['p','ur','p','le']]
当前输出:-
[]
您的代码几乎可以正常工作;只需要做一些小的改动就可以得到所需的输出:
- 如果目标为空,return
listOf(emptyList())
而不是 emptyList()
。
- 使用
add(0, word)
代替 add(word)
。
这些更改中的第一个是重要的。您的函数 return 是一个匹配列表;由于每个匹配项本身都是一个字符串列表,因此它 return 是一个字符串列表列表。一旦你的代码匹配了整个目标并最后一次调用自己,它 return 一个空列表——即没有匹配——而不是一个列表 包含 一个空列表——这意味着一场比赛,没有剩余的字符串。
第二个更改只是修复了每个匹配项中字符串的顺序,这是相反的(因为它在 returned 后缀匹配之后附加了前缀 。 =30=]
但是,还有许多其他方法可以改进代码。与其单独列出它们,不如给出一个替代版本可能更容易:
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 的扩展函数,因为它有效地 return 转换字符串,没有任何 side-effects — 不过,这往往在短函数上效果最好。
还有一些小调整。使用 startsWith()
或 endsWith()
而不是 indexOf()
更简单也更有效; removePrefix()
或 removeSuffix()
可以说比 substring()
更清晰;我发现 == ""
比 isEmpty()
.
更清晰
(此外,名称 howConstruct()
并没有很好地描述结果,但到目前为止我还没有想出更好的东西......)
其中许多更改当然是个人喜好问题,我相信其他开发人员会以许多其他方式编写它!但我希望这能提供一些想法。
我一直在编写代码,我必须在其中生成目标字符串的所有可能方式。我正在使用下面提到的代码。
打印报表:
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
}
预期输出:- [['purp','le'],['p','ur','p','le']]
当前输出:- []
您的代码几乎可以正常工作;只需要做一些小的改动就可以得到所需的输出:
- 如果目标为空,return
listOf(emptyList())
而不是emptyList()
。 - 使用
add(0, word)
代替add(word)
。
这些更改中的第一个是重要的。您的函数 return 是一个匹配列表;由于每个匹配项本身都是一个字符串列表,因此它 return 是一个字符串列表列表。一旦你的代码匹配了整个目标并最后一次调用自己,它 return 一个空列表——即没有匹配——而不是一个列表 包含 一个空列表——这意味着一场比赛,没有剩余的字符串。
第二个更改只是修复了每个匹配项中字符串的顺序,这是相反的(因为它在 returned 后缀匹配之后附加了前缀 。 =30=]
但是,还有许多其他方法可以改进代码。与其单独列出它们,不如给出一个替代版本可能更容易: 这与您的代码几乎完全相同,只是它从字符串的结尾(匹配后缀)而不是从开头进行搜索。结果是一样的;主要好处是将后缀字符串附加到部分匹配列表(使用 然而,它更简洁,主要是因为它使用了函数式风格——特别是,它使用 为了简单起见,我将其写成表达式主体(使用 还有一些小调整。使用 (此外,名称 其中许多更改当然是个人喜好问题,我相信其他开发人员会以许多其他方式编写它!但我希望这能提供一些想法。
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 的扩展函数,因为它有效地 return 转换字符串,没有任何 side-effects — 不过,这往往在短函数上效果最好。startsWith()
或 endsWith()
而不是 indexOf()
更简单也更有效; removePrefix()
或 removeSuffix()
可以说比 substring()
更清晰;我发现 == ""
比 isEmpty()
.howConstruct()
并没有很好地描述结果,但到目前为止我还没有想出更好的东西......)