scala模式匹配和正则表达式

匹配字面量和常量

    在actor间传递消息,通常用的是string字面量、数字或是元组。如果消息是字面量,只需要输入想匹配的字面量即可。

def activity(day : String) = {
	  day match {
	    case "monday" => print("work hard")
	    case "sunday" => print("eating sleeping ")
	    case "friday" => print("read a good book")
	    case "saturday" => print("met with friends")
	  }
	}
	List("monday", "sunday", "friday", "saturday").foreach {activity}
    match是一个队Any起作用的表达式。它会对目标执行模式匹配,根据匹配模式的值调用合适的case表达式。字面量和常量可以直接匹配。字面量可以是不同的类型。match并不关心。

匹配通配符

    如果有一个值,与case表达式里的任何一个都不匹配,会得到一个MatchError异常。通配符可以避免抛出异常。

private object WeekDay extends Enumeration {
	  val monday =  Value("monday")
	  val sunday =  Value("sunday")
	  val tuesday =  Value("tuesday")
	  
	}	
	
	def activity(day : WeekDay.Value) = {
	   day  match {
	     case WeekDay.monday => println()
	     case WeekDay.sunday => println()
	     case WeekDay.tuesday => println()
	     case _ => println("error")//通配符_,匹配剩下的日期
	   }
	}

匹配元素和列表

   元组和列表也可以用case表达式匹配。

def activity (input:Any) = {
	  input match {
	    case (a, b)/*匹配元组*/ => println()
	    case "done"/*匹配字面量*/ => println()
	    case _ => null
	  }
} 
    匹配List可以用匹配元组的方式匹配,仅仅提供关心的元素即可,上下的元素可以通过数组展开符号(_*)略去。

def processItem(items: List[String]) = {
	  items match {
	    case List("apple", "ibm") => println("apple\tIbm")
	    case List("red", "blue", "white") => println("red\tlue\twhite")
	    //匹配两项或更多
	    case List("red", "blue", _*) => println("red\tlue...")
	    //匹配两项或更多,如果需要在后续的block中引用,可以定义变量,引用剩下的
	    case List("orange", "pear",otherfruits @ _*) =>println("red\tlue" + otherfruits)
	  }
}

类型和卫述句的匹配

有时要处理的序列,其值可能是具有不同的类型。在scala中,case语句可以根据类型进行匹配。

def process(input:Any) = {
	  input match {
	    case (a:Int,b:Int) => {}
	    case (a:Double,b:Double) => {}
	    case msg : Int if (msg > 10000) => println("process input > 10000")
	    case msg : Int if (msg < 10000) => println("process input < 10000")
	    case _ => println("cannot hand anything")
	  }
}


case表达式里的模式变量和常量

    上例中,为匹配的val定义占位符(比如匹配元组的a和b)这就是模式变量。scala中的模式变量要以小写字母开头,常量以大写字母开头。

class MatchType {
	val max = 100
	val Min = 0
	def process(input:Int) = {
	  
	  input match {
	    /*
	     * 编译错误,scala将会认为max是一个模式变量,在当前范围内存在
	     */
	    case max => println("match max")
	    /*可行*/
	    case this.max => println("match max")
	    case Min => println("match min")	    
	    case _ => println("cannot hand anything")
	  }
	}
		
}


使用case类进行模式匹配

package com.fanshadoop
abstract class Trade
case class Sell(stocksym:String, number:Int) extends Trade
case class Buy(stocksym:String, number:Int) extends Trade
case class Hedge(stocksym:String, number:Int) extends Trade
class TradeProcessor {
	def process(stock:Trade) = {
	  stock match {
	    /*此处stockCoe,quality都是模式变量
	     * 如果股票代码和数量得到匹配,会存在模式变量中
	     * */
	    case Sell(stockCode, 1000) => println("selling stock:" + stockCode)
	    case Sell(stockCode, quaility) => println("selling stock:" + quaility)
	    case Buy(stockCode, quaility) if (quaility > 2000) => 
	                               println("buy stock:" + quaility)
	    case Buy(stockCode, quaility) => println("buy stock:" + quaility)
	  }
	}
}
case类也可以使用通配符。

使用提取器进行匹配

    scala提取器,匹配任意模式,会从输入中提取出匹配的部分。

package com.fanshadoop

object symbol {
   /*
    * 接受要匹配的值,返回Boolean
    * */
   def unapply(symbol : String) = {
     symbol == "IBM" || symbol == "GOOC"
   }
}
object ReceiveStockPrice {
   def unapply(input : String) : Option[(String, Double)] = {
      try {
        if (input contains ":") {
           val fields = input split  ":"
           Some(fields(0), fields(1).toDouble)
        } else {
          None
        }
      } catch {
        case _ : NumberFormatException => None
      }
   }
}
object Extractor {
    def process(input:String) = {
	      input match {
	        /*执行symbol()时,会自动把input传递给提取器的unapply方法
	         * 返回true时,执行相关的表达式
	         * */
	        case symbol() => println("look up stock price for "+ input)
	        /*
	         * 提取器ReceiveStockPrice将input传递给unapply方法
	         * symbol和price用于从unapply接受返回值
	         */
	        case ReceiveStockPrice(stock , price) => 
	             printf("Receive price %f for stock %s\n",price, stock)
	        case _ => println("invalid input " + input)
	      }
	}
    
	def main(args:Array[String]) = {
	   process("IBM")
	   process("GOOC")
	   process("IBM:100")
	   process("ERR:12.34")
	}
}

package com.fanshadoop

object symbol {
   /*
    * 接受要匹配的值,返回Boolean
    * */
   def unapply(symbol : String) = {
     symbol == "IBM" || symbol == "GOOC"
   }
}
object ReceiveStockPrice {
   def unapply(input : String) : Option[(String, Double)] = {
      try {
        if (input contains ":") {
           val fields = input split  ":"
           Some(fields(0), fields(1).toDouble)
        } else {
          None
        }
      } catch {
        case _ : NumberFormatException => None
      }
   }
}
object Extractor {
    def process(input:String) = {
	      input match {
	        /*执行symbol()时,会自动把input传递给提取器的unapply方法
	         * 返回true时,执行相关的表达式
	         * */
	        case symbol() => println("look up stock price for "+ input)
	        /*
	         * 首先应用ReceiveStockPrice,成功的话返回一对结果
	         * 对第一个结果进一步用symbol()提取器提取股票
	         */
	        case ReceiveStockPrice(stock @ symbol(), price) => 
	             printf("Receive price %f for stock %s\n",price, stock)
	        case _ => println("invalid input " + input)
	      }
	}    
}

正则表达式

    scala.uti.matching包里的类支持正则表达式。

//r()方法返回一个Regex实例
      val pattern = "(s|S)cala".r
      val str = """scala is scalable cool tools"""
      println(pattern.findAllMatchIn(str).mkString(", "))  

把正则表达式进行提取

    scala的正则表达式就是提取器。scala会把每个括号里的匹配都展开到一个模式变量里。比如"(S|s)cala".r有一个unapply()方法,它返回Option[String]。另一方面"(S|s)(cala)".r的unapply会返回Option[String,String]。

def process(input:String) = {
          val MatchStock = """^(.+):(\d+\.?\d*)""".r
	      input match {
	        case MatchStock(stock, price) => printf("stock=%s,price=%f\n", stock,price) 
	        case _ => println("invalid input " + input)
	      }
}   

展开阅读全文

没有更多推荐了,返回首页