在跳高比赛中,我对运动员的成绩有一定的了解。这里,+表示成功尝试,%不成功,-跳过。高度和相应的尝试用空格隔开。我需要读取字符串并返回最大高度,如果不存在或字符串格式损坏,则返回-1。 例如:
"220 + 224 %+ 228 %- 230 + 232 %%- 234 %".// result in 230
"226 +" // result is 226
"???" // result is -1
我尝试使用正则表达式,但没有取得太大的成功。
fun bestHighJump(jumps: String): Int {
var result = 0
val jumpsSplitted = jumps.split(" ")
val regStr = Regex("""[.+\d]""")
for (item in jumpsSplitted) {
if (regStr.containsMatchIn(item)) result += item
}
//Don't know what to do next
}
帮助解决问题,如果不是很困难,请推荐一些资源,使我可以很好地学习字符串格式设置主题。
答案 0 :(得分:2)
(鉴于问题已被改写。)
按照我现在的理解,该字符串应包含整数和符号,并且我们想要最大的整数,后跟“ +”。
我可以通过将字符串拆分成单词,然后查看单词的对来实现。我们可以使用zipWithNext()
函数来完成此操作,该函数给出所有相邻对的列表。然后,我们可以filter()
仅选择第二个单词为“ +”的单词,mapNotNull()
尽可能将这样的单词对中的第一个单词转换为Int
(忽略{{1 }}(不是有效整数),然后取其中的null
。 (如果没有,max()
返回max()
,所以我们可以使用Elvis运算符代替-1。)
null
(我将其作为fun String.bestHighJump()
= split(" ")
.zipWithNext()
.filter{ it.second == "+" }
.mapNotNull{ it.first.toIntOrNull() }
.max() ?: -1
的扩展函数,主要是因为它看起来很合适;它还避免了必须声明然后使用参数的情况。但是普通函数的工作方式几乎相同)
要使这更加惯用,最好删除Elvis运算符,如果没有匹配的分数,则直接返回String
;这使情况对于呼叫者来说更加明显,然后呼叫者可以决定如何处理该情况。
由于您正在查看正则表达式,因此这是使用其中一种的替代解决方案:
null
这短了一行,但是我认为它还不清楚。以我的经验,正则表达式通常很难正确设置,调试和维护,因此我更喜欢其他方法。 (为了进行比较,第一个版本是第一次工作,而regex版本却进行了许多尝试!)
此处正则表达式匹配一个成功的结果(一个或多个数字,后跟一个空格,一个fun String.bestHighJump()
= Regex("""([0-9]+) [+]\B""")
.findAll(this)
.map{ it.groupValues[1].toInt() }
.max() ?: -1
,然后一个单词边界。(需要后者,因为我们不知道此结果是否是正则表达式贪婪地匹配,因此我们也不需要一开始就使用它。)
+
搜索整个字符串,并返回一个匹配序列;然后,我们从每个数字中取出第一组(即数字),将其转换为整数(如果正则表达式有效,则这次无需处理无效数字),并像以前一样取最大值。
(关于如何处理具有多个字符的成功指示符的问题仍然不清楚。我假设我们只想对成功指示符只是一个字符'+'的结果进行计数。还包括在'%'和/或其他字符中包含'+'的情况,然后可以对这两个函数进行调整。但是同样,正则表达式将更难做到。)
关于在哪里学习这种东西,我假设您已经了解Kotlin docs。 (并且我推荐使用Kotlin In Action书来学习该语言。)根据您的需求,有不同的字符串处理方法,因此很难推荐-但基本原理并非特定于Kotlin,因此可能有很多地方可以看。而且,如果您的案子比较棘手,可以随时将其发布为另一个问题!
答案 1 :(得分:2)
首先,您需要修剪和清除多个相邻空格中的参数jumps
。
然后拆分后,创建2个列表:
第一个包含高度和
第二个包含尝试。
有必要检查第一个列表是否包含有效整数
并且这两个列表的大小相同。
然后,通过删除第二个列表的每个项目中所有出现的%
和-
,
您将获得最后+
个项目的索引。
此 index 用于从第一个列表中获取相应的高度。
fun bestHighJump(jumps: String): Int {
val jumpsSplitted = jumps.trim().replace(Regex("\\s\\s+"), " ").split(" ")
if (jumpsSplitted.size < 2 || jumpsSplitted.size % 2 == 1)
return -1
val heights = jumpsSplitted.filterIndexed { i, _ -> (i % 2 == 0)}.mapNotNull { it.toIntOrNull() }
val attempts = jumpsSplitted.filterIndexed { i, _ -> (i % 2 == 1)}
if (heights.size != attempts.size)
return -1
val index = attempts
.map { it.replace("%", "").replace("-", "") }
.indexOfLast { it == "+" }
return if (index == -1) -1 else heights[index]
}
这个
val jumps1 = "220 + 224 %+ 228 %- 230 + 232 %%- 234 %"
println(bestHighJump(jumps1))
将打印230
这个
val jumps2 = "226 +"
println(bestHighJump(jumps2))
将打印226
这个
val jumps3 = "???"
println(bestHighJump(jumps3))
将打印-1
答案 2 :(得分:1)
使用正则表达式是个好主意。团体在这里特别方便。
([\\d]{1,3})([ +\\-%]*)
正则表达式将在其第一组中匹配任何1-3位数字,并在第二组中匹配该尝试的结果。
您用Sequence<MatchResult>
检索了findAll
,然后过滤并映射了感兴趣的值。
最后,您将返回成功尝试的最大值;如果输入字符串无效或不包含成功跳转,则返回-1。
fun bestHighJump(jumps: String): Int {
val attempts = Regex("([\\d]{1,3})([ +\\-%]*)").findAll(jumps)
val list = attempts.filter {
it.groups[2]?.value?.let {
'+' in it
} == true
}.map {
it.groups[1]?.value
}.mapNotNull { it?.toInt() }.toList()
return if (list.isEmpty()) {
-1
} else {
list.max()!!
}
}
请注意,在Kotlin的MatchGroupCollection
中,第一组的索引为1,第二组的索引为2,因为索引为0的组是两个组的组合。