簡體   English   中英

Scala模式匹配_符號

[英]Scala pattern matching _ symbol

我是Scala的新手。 在我以前的帖子中,有人提供了一段我無法正確理解的代碼。

type JsonMap = Map[String, Any]

def getMapDiffs(mapBefore: JsonMap, mapAfter: JsonMap) : (JsonMap, JsonMap) = {
  val sameKeys = mapBefore.keySet intersect mapAfter.keySet
  val startAcc = (Map.empty[String, Any], Map.empty[String, Any])
  sameKeys.foldLeft(startAcc){ case (acc @ (deltaBefore, deltaAfter), key) =>
    (mapBefore(key), mapAfter(key)) match {
      // two maps -> add map diff recursively to before diff and after diff
      case (beforeMap: Map[_, _], afterMap: Map[_, _]) =>
        val (deltaB, deltaA) = 
          getMapDiffs(beforeMap.asInstanceOf[JsonMap], afterMap.asInstanceOf[JsonMap])
        (deltaBefore + (key -> deltaB), deltaAfter + (key -> deltaA))
      // values before and after are different
      // add values to before diff and after diff
      case (beforeValue, afterValue) if beforeValue != afterValue =>
        (deltaBefore + (key -> beforeValue), deltaAfter + (key -> afterValue))
      // keep existing diff  
      case _ => acc
    }  
  }
}

有人可以向我解釋case _ => acc在做什么case _ => acc嗎? 如果有人想深入解釋所有同樣適用的代碼,因為我正在嘗試使用函數式編程。

干杯!

首先要問的是,雖然標題中的@我不明白。

_是scala中的通配符。 因此,在上面的代碼中

case _ => acc

匹配之前未匹配的所有案例。 在上面的代碼中, mapBeforemapAfter中所有具有相同鍵的值都沒有區別。 因此,保留了前一個折疊周期的結果,而在其他情況下,將添加不同值的對。

現在介紹其余的代碼(我不是作者,但我可以猜測):

type JsonMap = Map[String, Any]

是為了簡潔和方便而定義的類型別名。

def getMapDiffs(mapBefore: JsonMap, mapAfter: JsonMap) : (JsonMap, JsonMap) = {
  val sameKeys = mapBefore.keySet intersect mapAfter.keySet
  val startAcc = (Map.empty[String, Any], Map.empty[String, Any])

samekeys是在兩個輸入映射中定義的一組鍵startAcc是即將到來的foldLeft的起始值。

sameKeys.foldLeft(startAcc){ case (acc @ (deltaBefore, deltaAfter), key) =>

foldLeft采用一個起始值,然后遍歷已被調用的集合。 對於集合的每個項目,將最后一步的結果和集合的當前元素作為折疊功能的輸入。 在第一步中,起始值將替換結果。

該函數調用可以重寫為:

sameKeys.foldLeft(startAcc){ inputTuple: ((JsonMap, JsonMap), String) =>

但是,由於您隨后將不得不以相當繁瑣且難以理解的方式訪問元組內容(例如,inputTuple._1._2以獲取先前結果的第二張地圖),因此開發人員利用了以下事實:我們可以直接將輸入與fold,map,flatMap等功能。 從而

case (acc @ (deltaBefore, deltaAfter), key) =>

將兩個元組的內容綁定到可讀的本地val,並將元組本身綁定到acc(這就是@的含義)。 這樣,我們可以方便地使用兩個映射以及上次迭代的完整結果元組,這在默認情況下( case _ => acc )特別有用

(mapBefore(key), mapAfter(key)) match {

從兩個輸入映射中檢索同一當前鍵的值,然后開始匹配。

case (beforeMap: Map[_, _], afterMap: Map[_, _]) =>
    val (deltaB, deltaA) = 
      getMapDiffs(beforeMap.asInstanceOf[JsonMap], afterMap.asInstanceOf[JsonMap])
    (deltaBefore + (key -> deltaB), deltaAfter + (key -> deltaA))

匹配本身是Map的值,並應用遞歸函數以獲取這些映射的所有差異,並將它們添加到此折疊步驟的結果中。

case (beforeValue, afterValue) if beforeValue != afterValue =>
    (deltaBefore + (key -> beforeValue), deltaAfter + (key -> afterValue))

匹配兩個相等的輸入映射的所有其他值,並將它們添加到此折疊步驟的結果中。

因此,最后您應該獲得兩個具有相同keySet的映射,並且在原始兩個輸入映射中所有不同的值。

每個模式都與case _ =>匹配。 這就像elseif-elsedefault情況下,Java的switch塊。 在您的代碼中,如果(mapBefore(key), mapAfter(key))不匹配

(beforeMap: Map[_, _], afterMap: Map[_, _])

(beforeValue, afterValue) if beforeValue != afterValue

它將始終與_匹配,並在執行case _ =>之后執行代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM