目标:编写一个生成新字符串的函数,不包括指定字符(由索引标识)
示例:
takeAllExcept(0, "abc")
返回bc
takeAllExcept(1, "abc")
返回ac
takeAllExcept(2, "abc")
返回ab
我最初做了什么:
def takeAllExcept( index: Int, s: String ): String = {
val lastIndex = s.length()-1
index match {
case 0 => return s.slice(1, s.length)
case lastIndex => return s.slice(0, s.length()-1)
case _ => { s.slice(0, index) + s.slice(index+1, s.length) }
}
}
编译器抱怨case _
的语句块无法访问。
我是如何修理的
def takeAllExcept( index: Int, s: String ): String = {
val lastIndex = s.length()-1
if( index == 0 )
return s.slice(1, s.length)
if( index == lastIndex )
return s.slice(0, s.length()-1)
s.slice(0, index) + s.slice(index+1, s.length)
}
我想知道为什么我的初始尝试因无法访问的代码而失败。它看起来很合法。另外,scala中是否有内置工具可以执行此操作?
答案 0 :(得分:10)
lastIndex
是一个新名称的隐式声明,它绑定到匹配中的任何值,并影响已经定义的lastIndex
,正如其他两个帖子已经指出的那样。还有两种可能性,而不是使用大写标识符(参见Peter的帖子):
使用反引号让编译器知道这不应该是新标识符的声明:
case `lastIndex` => ...
使用图案防护:
case x if x == lastIndex => ...
如果你想对字符串进行大量基于索引的删除,那么通过调用字符串上的toBuffer
来使用Buffer会更快,然后你可以使用Buffer的remove(i: Int)
方法。这对于一个操作来说速度较慢,因为你必须在完成后将Buffer转换回字符串,但如果你做了很多随机访问操作,它会快得多。完成后,您可以在缓冲区上调用mkString
以获取字符串。对于单一删除,我会像Peter建议的那样做,或者这是另一种选择:
def takeAllExcept(i: Int, s: String) = s.take(i) + s.drop(i+1)
答案 1 :(得分:6)
你的第一个问题:
def takeAllExcept( index: Int, s: String ): String = {
val LastIndex = s.length()-1
index match {
case 0 => return s.slice(1, s.length)
case LastIndex => return s.slice(0, s.length()-1)
case _ => { s.slice(0, index) + s.slice(index+1, s.length) }
}
}
lastIndex
之后case
新绑定模式匹配并隐藏val lastIndex = s.length()-1
的定义。正如我的示例所示,您可以使用大写名称,然后scala在范围内使用已定义的val
。
以某种方式回答你的第二个问题我会解决它:
def takeAllExcept(i: Int, s: String): String = {
val (prefix,suffix) = s.splitAt(i)
prefix + suffix.tail
}
答案 2 :(得分:1)
val lastIndex = s.length()-1
index match {
case 0 => return s.slice(1, s.length)
case lastIndex => return s.slice(0, s.length()-1)
case _ => { s.slice(0, index) + s.slice(index+1, s.length) }
}
第二个子句不会尝试将index
与lastIndex
匹配,就像您期望的那样。序言。相反,它匹配任何值并将值绑定到名称lastIndex
,隐藏此变量的先前绑定。