如何在Scala中对匹配数组进行模式化?


68

我的方法定义如下

def processLine(tokens: Array[String]) = tokens match { // ...

假设我想知道第二个字符串是否为空

case "" == tokens(1) => println("empty")

不编译。我该怎么做呢?


我不太了解您要达到的目标。测试Array的第二个条目是否为空String,如果是,则打印“ empty”?其次,您的“方法签名”缺少返回类型说明,并包含一些代码(即tokens match {})。
ziggystar 2011年

Answers:


110

如果要在阵列上进行模式匹配以确定第二个元素是否为空字符串,则可以执行以下操作:

def processLine(tokens: Array[String]) = tokens match {
  case Array(_, "", _*) => "second is empty"
  case _ => "default"
}

_*结合到任何数量的元件,包括无。这类似于列表上的以下匹配,这可能是众所周知的:

def processLine(tokens: List[String]) = tokens match {
  case _ :: "" :: _ => "second is empty"
  case _ => "default"
}

2
如何图案匹配尾巴?它留为_ *
devssh

2
@devsshtail @ _*
Abhijit Sarkar,

那么_*是匿名变量吗?如果要在case块内打印此尾巴的值,该怎么办?如果我这样做,case a则可以a在case块内使用,但是如果执行case _此操作,则该变量在case块内将不可用。你能解释更多吗?我尝试使用Array(a,b,c),但它将匹配大小为3的数组,而不是大小为n的数组。
devssh

7

什么是格外有趣的是,你可以使用一个别名通过匹配的东西,_*喜欢的东西

val lines: List[String] = List("Alice Bob Carol", "Bob Carol", "Carol Diane Alice")

lines foreach { line =>
  line split "\\s+" match {
    case Array(userName, friends@_*) => { /* Process user and his friends */ }
  }
}

6

模式匹配可能不是您的示例的正确选择。您可以简单地执行以下操作:

if( tokens(1) == "" ) {
  println("empty")
}

模式匹配更适合以下情况:

for( t <- tokens ) t match {
   case "" => println( "Empty" )
   case s => println( "Value: " + s )
}

为每个令牌打印一些东西。

编辑:如果您要检查是否有任何令牌是一个空字符串,您也可以尝试:

if( tokens.exists( _ == "" ) ) {
  println("Found empty token")
}

2
那肯定是可行的,但似乎是程序上的做事方式。我正在尝试从功能上进行思考
2011年

是的,因为您的问题是程序性的回答。对于更实用的方法,您可以将每个元素映射到字符串的选项,当字符串为空时,该选项将为None。您也可以将行包装在地图(或案例类)中,以停止显式运行索引。
范式

6
@deltanovember这println就是使您的代码具有过程性的原因。您明显的困惑源于这样的事实:if在Scala中,块是表达式而不是语句(即,它们返回值,因此功能完善)。使用if表达式而不是模式匹配并没有固有的程序性。
亚伦·诺夫斯特鲁普

3

case声明不能那样工作。应该是:

case _ if "" == tokens(1) => println("empty")

如果我想分别检查tokens(1),tokens(2),...怎么办?
2011年

+1是一个可行的解决方案,但我想知道OP是否不希望在case关键字后添加一些复杂的类似于数组的表达式,例如(_, "", _). Saying case _`很无聊,但我认为这是您可以做的所有事情。也可以取消比赛并说return tokens(1) == "":-)。
雷·托尔

1
@Ray Toal:请参阅Ruediger Keller的答案。
阿列克谢·罗曼诺夫

2
哇。Scala永不停息。以这种速度,我将完全远离ML。
雷·托尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.