[英]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
匹配之前未匹配的所有案例。 在上面的代碼中, mapBefore和mapAfter中所有具有相同鍵的值都沒有區別。 因此,保留了前一個折疊周期的結果,而在其他情況下,將添加不同值的對。
現在介紹其余的代碼(我不是作者,但我可以猜測):
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 _ =>
匹配。 這就像else
在if-else
或default
情況下,Java的switch
塊。 在您的代碼中,如果(mapBefore(key), mapAfter(key))
不匹配
(beforeMap: Map[_, _], afterMap: Map[_, _])
或
(beforeValue, afterValue) if beforeValue != afterValue
它將始終與_
匹配,並在執行case _ =>
之后執行代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.