[英]What is a more functional way of creating a Map of List?
我有此工作代碼可在字符串中的字符和包含索引的列表之間創建映射。
scala> "Lollipop".zipWithIndex.foldLeft(Map[Char, List[Int]]())((acc, t) => acc + (t._1 -> (acc.getOrElse(t._1, List[Int]()) :+ t._2)))
res122: scala.collection.immutable.Map[Char,List[Int]] = Map(i -> List(4), L -> List(0), l -> List(2, 3), p -> List(5, 7), o -> List(1, 6))
但是使用acc.getOrElse
看起來勢在必行。 有沒有更實用的方法可以將其隱藏在用戶面前?
for {
(c, l) <- "Lollipop".zipWithIndex.groupBy{ _._1 }
} yield c -> l.map{ _._2 }
// Map(i -> Vector(4), L -> Vector(0), l -> Vector(2, 3), p -> Vector(5, 7), o -> Vector(1, 6))
在groupBy{ _._1 }
您將獲得Map[Char, Seq[(Char, Int)]]
。 因此,您必須使用p => p._2
或僅_._2
p => p._2
(Char, Int)
轉換為Int
。
您可以這樣使用mapValues
:
"Lollipop".zipWithIndex.groupBy{ _._1 }.mapValues{ _.map{_._2} }
但是mapValues
創建了一個惰性集合,因此在通過鍵多次訪問同一元素的情況下,您可能會遇到性能問題。
另一種方法是為地圖使用默認值(稍微重寫一下代碼以使內容更明確):
val empty = Map.empty[Char, List[Int]].withDefaultValue(List.empty)
"Lollipop".zipWithIndex.foldLeft(empty) {
case (acc, (char, position)) => {
val positions = acc(char) :+ position
acc + (char -> positions)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.