程式扎記: [Scala 小學堂] Scala Gossic : 起步走 - 常用物件 (Set 與 Map)

標籤

2016年5月11日 星期三

[Scala 小學堂] Scala Gossic : 起步走 - 常用物件 (Set 與 Map)

轉載自 這裡 
前言 : 
Scala 是一個可直譯、編譯、靜態、運行於 JVM 之上、可與 Java 互操作、融合物件導向編程特性與函式編程風格的程式語言. 從一些簡單的語法開始,了解 Scala 的許多特性,所以就算是起步走,東西也夠多了. 簡單的小程式可以使用 scala 指令,編譯的事就交給 scalac,編譯想快點就用 fsc. (Scala 官網), 在變與不變之間,先體會 Scala 更多特性. 

Set 介紹 : 
Set 無序集合物件,物件所收集的元素不重複。在 Scala 中,預設的 Set 實作是不可變動的Immutable),如果你要建立 Set 實例,以下是個例子 : 
- SetMap1.scala 代碼 :
  1. val names1 = Set("John""Peter""Ken")  
  2. names1.foreach(println)  
  3.   
  4. val names2 = names1 + "John"  
  5. names2.foreach(println)  
  6.   
  7. val names3 = names1 + "Bob"  
  8. names3.foreach(println)  

+ 可用來於集合中新增元素,由於預設的 Set 實作是不可變動的,所以實際上會建立一個新的 Set 物件傳回,但由於 Set 中的元素不重複,如果要加入的元素是 重複的,就會直接傳回原來的 Set 實例,因此範例中 names2 中實際上並沒有增加元素,而且直接傳回 names1的實例. 要從元素中刪 除某個元素,可以使用 - 方法。如果要串接兩個 Set,則可以使用 ++也就是聯集操作,因為 Set 不允許重複),如果要從某個 Set 中,刪去另一個 Set 物件所指定的元素,則可以使用 --,如果要作交集操作,則使用 **,如果要比較兩個 Set 物件的內含元素是否相同,可以直接使用 ==。以下是直接從直譯環 境作個示範 : 
scala> val x = Set(1,2,3,4,5)
x: scala.collection.immutable.Set[Int] = Set(4, 5, 1, 2, 3)

scala> x - 2
res0: scala.collection.immutable.Set[Int] = Set(4, 5, 1, 3)

scala> x ++ Set(6, 7, 8, 9)
res1: scala.collection.immutable.Set[Int] = Set(8, 4, 9, 5, 6, 1, 2, 7, 3)

scala> x -- Set(2, 3)
res2: scala.collection.immutable.Set[Int] = Set(4, 5, 1)

scala> x ** Set(3, 4, 5, 6, 7)
warning: there were deprecation warnings; re-run with -deprecation for details
res3: scala.collection.immutable.Set[Int] = Set(4, 5, 3)

scala> x == Set(1, 2, 3, 4, 5)
res4: Boolean = true

剛剛提過,預設的 Se t實作是不可變動的,實際上,預設是使用 scala.collection.immutable.Set 的實作(事實上,不可變動的群集定義都是位於 scala.collection.immutable 套件之中),如果你需要可變動的 Set,則可以匯入(importscala.collection.mutable.Set可變動的群集定義都是位於 scala.collection.mutable 套件之中).例如 : 
- SetMap2.scala 代碼 :
  1. import scala.collection.mutable.Set  
  2.   
  3. val names = Set("John""Peter""Ken")  
  4. names.foreach(println)  
  5.   
  6. names += "Mary"  
  7. names.foreach(println)  

在上例中,呼叫了names 的 += 方法,由於你匯入了 scala.collection.mutable.Set,所以使用的是可變動的 Set,+= 是該 Set 實作物件上的方法,這會將元素加入同一個 Set 實例,而不是建立新的 Set 實例. 事實上,先前未匯入scala.collection.mutable.Set 時,你程式中所使用的 Set 名稱所參考的物件,其實是定義在 scala.Predef 中 : 
  1. package scala  
  2. object Predef {  
  3.     ...  
  4.     type Map[A, B] = collection.immutable.Map[A, B]  
  5.     type Set[A] = collection.immutable.Set[A]  
  6.   
  7.     val Map = collection.immutable.Map  
  8.     val Set = collection.immutable.Set  
  9.     ...  
  10. }  
val 宣告了Map 與 Set 分別參考至 collection.immutable.Set 與 collection.immutable.Map 物件,而 type 為 collection.immutable.Set[A] 與 collection.immutable.Map[A, B] 建立了別名 Set[A] 與 Map[A, B]. 

Map 介紹 : 
Map 是具有鍵/值(Key/Value)的字典物件。在 Scala 中預設的 Map 實作是不可變動的,理由在上面的程式碼片段可以看到,預設的Map是 collection.immutable.Map 的實作。要建立 Map 物件,以下是個範例 : 
- SetMap3.scala 代碼 :
  1. val rooms = Map(101 -> "John"102 -> "Ken")  
  2. println(rooms(101))  
  3. println(rooms(102))  

-> 左邊指定鍵,右邊是值。指定鍵要取回值時,是使用 (),從先前的介紹你大概也可以推論出,rooms(101) 這樣的指定時,其實會轉換為呼叫 rooms.apply(101) 這樣的呼叫。由於預設的 Map 是不可變動的,所以如下要更新 Map 中的元素,實際上會傳回新的 Map 物件,例如 : 
- SetMap4.scala 代碼 :
  1. val rooms = Map(101 -> "John"102 -> "caterpillar")  
  2.   
  3. // 下面真正是變成 val newRooms = rooms.apply(101, "Hamimi")  
  4. val newRooms = rooms(101) = "Bob" //或可以寫成 val newRooms = rooms.updated(101, "Bob")    
  5. println(rooms(101))      // 顯示 John  
  6. println(newRooms(101))   // 顯示 Ken  

範 例中第二行程式碼其實是很不直覺,因為 = 運算應該是沒有傳回值的(也就是結果是Unit),不過事實上如註解中所說明的,rooms(101) = "Hamimi" 實際上會變成 rooms.update(101, "Hamimi"),而 update 方法傳回的是新的 Map 物件. 同樣的,如果你要使用可變動的 Map 實作,則可以匯入 collection.mutable.Map,例如 : 
- SetMap5.scala 代碼 :
  1. import collection.mutable.Map  
  2.   
  3. val rooms = Map[String, String]()  
  4. rooms("101") = "John"  
  5. println(rooms("101"))  
  6.   
  7. rooms += ("102" -> "Ken")  
  8. rooms.foreach(println)  

這個例子同時示範了如何新增鍵/值元素至Map中,也就是使用 ("102" -> "Ken") 這樣的寫法,另外也示範了,在呼叫 Map 的 foreach 方法時,每次 foreach 會取得 Tuple 物件,代表了該次迭代時的鍵/值,這個例子會顯示以下的結果 : 
John
(101,John)
(102,Ken)

下面這個例子則示範如何使用傳入的 Tuple : 
- SetMap6.scala 代碼 :
  1. import collection.mutable.Map  
  2. val rooms = Map[String, String]()  
  3.   
  4. rooms("101") = "John"  
  5. rooms += ("102" -> "Ken")  
  6. rooms.foreach(element => {  
  7.                                 val (key, value) = element  
  8.                                 println(key+" : "+value)  
  9.                          })  

這個例子會顯示以下的結果 : 
101 : John
102 : Ken

補充說明 : 
Tutorialspoint - Scala Collections 

沒有留言:

張貼留言

網誌存檔