假設我這樣val someMap = Map[String -> Map[String -> String]]定義:
val someMap =
Map(
("a1" -> Map( ("b1" -> "c1"), ("b2" -> "c2") ) ),
("a2" -> Map( ("b3" -> "c3"), ("b4" -> "c4") ) ),
("a3" -> Map( ("b5" -> "c5"), ("b6" -> "c6") ) )
)
我想把它壓平成看起來像的東西
List(
("a1","b1","c1"),("a1","b2","c2"),
("a2","b3","c3"),("a2","b4","c4"),
("a3","b5","c5"),("a3","b6","c6")
)
這樣做的最有效方法是什么?我正在考慮創建一些輔助函式來處理每個(a_i -> Map(String,String))鍵值對并回傳
def helper(key: String, values: Map[String -> String]): (String,String,String)
= {val sublist = values.map(x => (key,x._1,x._2))
return sublist
}
然后將這個函式平面映射到someMap. 但這對我的 scala 新手來說似乎有些不必要,所以我想知道是否有更有效的方法來決議這個 Map。
uj5u.com熱心網友回復:
無需創建輔助函式,只需撰寫嵌套的 lambda:
val result = someMap.flatMap { case (k, v) => v.map { case (k1, v1) => (k, k1, v1) } }
或者
val y = someMap.flatMap(x => x._2.map(y => (x._1, y._1, y._2)))
uj5u.com熱心網友回復:
既然你問的是效率,我能想到的最有效但最實用的方法是使用foldLeftand foldRight。
您需要foldRight因為::反向構造不可變串列。
someMap.foldRight(List.empty[(String, String, String)]) { case ((a, m), acc) =>
m.foldRight(acc) {
case ((b, c), acc) => (a, b, c) :: acc
}
}
在這里,假設Map.iterator.reverse有效實施,則不會創建中間集合。
或者,您可以使用foldLeft然后reverse結果:
someMap.foldLeft(List.empty[(String, String, String)]) { case (acc, (a, m)) =>
m.foldLeft(acc) {
case (acc, (b, c)) => (a, b, c) :: acc
}
}.reverse
這樣List就創建了一個中間體,但您不依賴于反向迭代器的實作(foldLeft使用正向迭代器)。
注意: one liner 的someMap.flatMap(x => x._2.map(y => (x._1, y._1, y._2)))效率較低,因為除了用于保存 的中間結果的臨時緩沖區之外flatMap,它們還會為每個內部map.創建和丟棄額外的中間集合。
UPD
由于似乎有些混亂,我將澄清我的意思。下面是一個實作map,flatMap,foldLeft和foldRight來自TraversibleLike:
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
def builder = { // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
val b = bf(repr)
b.sizeHint(this)
b
}
val b = builder
for (x <- this) b = f(x)
b.result
}
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
def builder = bf(repr) // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
val b = builder
for (x <- this) b = f(x).seq
b.result
}
def foldLeft[B](z: B)(op: (B, A) => B): B = {
var result = z
this foreach (x => result = op(result, x))
result
}
def foldRight[B](z: B)(op: (A, B) => B): B =
reversed.foldLeft(z)((x, y) => op(y, x))
很明顯,mapandflatMap創建中間緩沖區使用相應的builder,whilefoldLeft和foldRight重用相同的用戶提供的累加器物件,并且只使用迭代器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/333171.html
下一篇:ScalaXML決議多個欄位
