为什么scala在给出这个模式匹配的积分值时会抱怨?

时间:2011-03-01 11:03:41

标签: scala pattern-matching

目标:编写一个生成新字符串的函数,不包括指定字符(由索引标识)

示例

  • 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中是否有内置工具可以执行此操作?

3 个答案:

答案 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) }
}

第二个子句不会尝试将indexlastIndex匹配,就像您期望的那样。序言。相反,它匹配任何值并将值绑定到名称lastIndex,隐藏此变量的先前绑定。