Scala 基礎(十五):Scala 模式匹配(三)

1 變量聲明中的模式

match中每個case均可以單獨提取出來,意思是同樣的.程序員

應用案例正則表達式

val (x, y) = (1, 2)
val (q, r) = BigInt(10) /% 3  //說明  q = BigInt(10) / 3 r = BigInt(10) % 3
val arr = Array(1, 7, 2, 9)
val Array(first, second, _*) = arr // 提出arr的前兩個元素
println(first, second)

2 for表達式中的模式

for循環也能夠進行模式匹配.app

應用案例測試

val map = Map("A"->1, "B"->0, "C"->3)
for ( (k, v) <- map ) {
println(k + " -> " + v)
}
//說明
for ((k, 0) <- map) {
println(k + " --> " + 0)
}
//說明
for ((k, v) <- map if v == 0) {
println(k + " ---> " + v)
}

3 樣例類

樣例類快速入門優化

abstract class Amount
case class Dollar(value: Double) extends Amount 
case class Currency(value: Double, unit: String) extends Amount
case object NoAmount extends Amount 

說明: 這裏的 Dollar,Currencry, NoAmount  是樣例類。

基本介紹spa

1)樣例類仍然是類設計

2)樣例類用case關鍵字進行聲明。3d

3)樣例類是爲模式匹配而優化的類rest

4)構造器中的每個參數都成爲val——除非它被顯式地聲明爲var(不建議這樣作)code

5)在樣例類對應的伴生對象中提供apply方法讓你不用new關鍵字就能構造出相應的對象

6)提供unapply方法讓模式匹配能夠工做

7)將自動生成toString、equals、hashCode和copy方法(有點相似模板類,直接給生成,供程序員使用)

8)除上述外,樣例類和其餘類徹底同樣。你能夠添加方法和字段,擴展它們

樣例類最佳實踐1:

當咱們有一個類型爲Amount的對象時,能夠用模式匹配來匹配他的類型,並將屬性值綁定到變量(即:把樣例類對象的屬性值提取到某個變量,該功能有用)

for (amt <- Array(Dollar(1000.0), Currency(1000.0, "RMB"), NoAmount)) {
val result = amt match {
//說明
case Dollar(v) => "$" + v
//說明
case Currency(v, u) => v + " " + u
case NoAmount => ""
}
println(amt + ": " + result)
}

樣例類最佳實踐2:

樣例類的copy方法和帶名參數

copy建立一個與現有對象值相同的新對象,並能夠經過帶名參數來修改某些屬性。

val amt = Currency(29.95, "RMB")
val amt1 = amt.copy() //建立了一個新的對象,可是屬性值同樣
val amt2 = amt.copy(value = 19.95) //建立了一個新對象,可是修改了貨幣單位
val amt3 = amt.copy(unit = "英鎊")//..
println(amt)
println(amt2)
println(amt3)

4 case語句的中置(綴)表達式

什麼是中置表達式?1 + 2,這就是一箇中置表達式。若是unapply方法產出一個元組,你能夠在case語句中使用中置表示法。好比能夠匹配一個List序列

應用實例

List(1, 3, 5, 9) match { //修改並測試
//1.兩個元素間::叫中置表達式,至少first,second兩個匹配才行.
//2.first 匹配第一個 second 匹配第二個, rest 匹配剩餘部分(5,9)
case first :: second :: rest => println(first + second + rest.length) //
case _ => println("匹配不到...")
}

5 匹配嵌套結構

操做原理相似於正則表達式

最佳實踐案例-商品捆綁打折出售

如今有一些商品,請使用Scala設計相關的樣例類,完成商品捆綁打折出售。要求

1)商品捆綁能夠是單個商品,也能夠是多個商品。

2)打折時按照折扣x元進行設計.

3)可以統計出全部捆綁商品打折後的最終價格

建立樣例類

abstract class Item //

case class Book(description: String, price: Double) extends Item
//Bundle 捆 , discount: Double 折扣 , item: Item* , 
case class Bundle(description: String, discount: Double, item: Item*) extends Item

匹配嵌套結構(就是Bundle的對象) 

//給出案例表示有一捆數,單本漫畫(40-10) +文學做品(兩本書)(80+30-20) = 30 + 90 = 120.0
val sale = Bundle("書籍", 10,  Book("漫畫", 40), Bundle("文學做品", 20, Book("《陽關》", 80), Book("《圍城》", 30))) 

知識點1-將descr綁定到第一個Book的描述

val sale = Bundle("書籍", 10,  Book("漫畫", 40), Bundle("文學做品", 20, Book("《陽關》", 80), Book("《圍城》", 30)))
val res = sale match  {
//若是咱們進行對象匹配時,不想接受某些值,則使用_ 忽略便可,_* 表示全部
case Bundle(_, _, Book(desc, _), _*) => desc
}

知識點2-經過@表示法將嵌套的值綁定到變量。_*綁定剩餘Item到rest

val sale = Bundle("書籍", 10,  Book("漫畫", 40), Bundle("文學做品", 20, Book("《陽關》", 80), Book("《圍城》", 30)))

這個嵌套結構中的 "漫畫" 和 紫色的部分 綁定到變量,即賦值到變量中.

val result2 = sale match {
case Bundle(_, _, art @ Book(_, _), rest @ _*) => (art, rest)
}
println(result2)
println("art =" + result2._1)
println("rest=" + result2._2)

知識點3-不使用_*綁定剩餘Item到rest

 

 

val result2 = sale match {
//說明由於沒有使用 _* 即明確說明沒有多個Bundle,因此返回的rest,就不是WrappedArray了。
case Bundle(_, _, art @ Book(_, _), rest) => (art, rest)
}
println(result2)
println("art =" + result2._1)
println("rest=" + result2._2)

6 密封類

 

 

相關文章
相關標籤/搜索