将可变字符串集的映射转换为 Scala 中不可变字符串集的映射
Convert Map of mutable Set of strings to Map of immutable set of strings in Scala
我有一个 "dirtyMap",它是 immutable.Map[String,collection.mutable.Set[String]]。我想将 dirtyMap 转换为不可变的 Map[String, Set[String]]。你能告诉我怎么做吗?我尝试了几种没有产生积极结果的方法
方法一:使用map函数
dirtyMap.toSeq.map(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
我遇到语法错误
方法二:使用foreach
dirtyMap.toSeq.foreach(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
无法将 toMap 应用于 foreach 的输出
免责声明:如果您不知道,我是 Scala 菜鸟。
更新:当我从 toMap() 函数中删除括号时,方法 1 有效。然而,下面是一个优雅的解决方案
dirtyMap.mapValues(v => v.toSet)
感谢 Gabriele 提供的答案和很好的解释。也感谢 Duelist 和 Debojit 的回答
你可以用flatMap
来做:
dirtyMap.flatMap(entry => Map[String, Set[String]](entry._1 -> entry._2.toSet)).toMap
首先,您 map
immutable.Map(entry)
的每个条目都有更新的条目,现在的值为 immutable.Set
。您的地图如下所示:mutable.Map。
然后 flatten
被调用,因此每个带有 immutable.Set
的条目都会得到 mutable.Map
。然后 toMap 将此映射转换为不可变的。
这个变体有点复杂,你可以像 Debojit Paul 提到的那样使用 dirtyMap.map(...).toMap
。
另一种变体是foldLeft
:
dirtyMap.foldLeft(Map[String, Set[String]]())(
(map, entry) => map + (entry._1 -> entry._2.toSet)
)
您指定累加器,即 immutable.Map
并使用转换后的集合将每个条目添加到此映射。
对于我来说,我认为使用 foldLeft
是更有效的方法。
您可以使用
dirtyMap.map({case (k,v) => (k,v.toSet)})
你可以简单地做:
dirtyMap.mapValues(_.toSet)
mapValues
只会将函数应用于 Map
的值,而 .toSet
会将可变的 Set
转换为不可变的
(我假设 dirtyMap
是一个 collection.immutable.Map
。如果它是可变的,只需在最后添加 toMap
)
如果您不熟悉 lambda 的下划线语法,它是 shorthand for:
dirtyMap.mapValues(v => v.toSet)
现在,由于 ()
,您的第一个示例无法编译。 toMap
不带显式参数,但它带隐式参数。如果您希望自动推断隐式参数,只需删除 ()
.
第二个示例不起作用,因为 foreach
returns Unit
。这意味着 foreach
会执行副作用,但它不会 return 一个值。如果你想对一个值进行链式转换,切勿使用 foreach
,而是使用 map
。
我有一个 "dirtyMap",它是 immutable.Map[String,collection.mutable.Set[String]]。我想将 dirtyMap 转换为不可变的 Map[String, Set[String]]。你能告诉我怎么做吗?我尝试了几种没有产生积极结果的方法
方法一:使用map函数
dirtyMap.toSeq.map(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
我遇到语法错误
方法二:使用foreach
dirtyMap.toSeq.foreach(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
无法将 toMap 应用于 foreach 的输出
免责声明:如果您不知道,我是 Scala 菜鸟。
更新:当我从 toMap() 函数中删除括号时,方法 1 有效。然而,下面是一个优雅的解决方案
dirtyMap.mapValues(v => v.toSet)
感谢 Gabriele 提供的答案和很好的解释。也感谢 Duelist 和 Debojit 的回答
你可以用flatMap
来做:
dirtyMap.flatMap(entry => Map[String, Set[String]](entry._1 -> entry._2.toSet)).toMap
首先,您 map
immutable.Map(entry)
的每个条目都有更新的条目,现在的值为 immutable.Set
。您的地图如下所示:mutable.Map。
然后 flatten
被调用,因此每个带有 immutable.Set
的条目都会得到 mutable.Map
。然后 toMap 将此映射转换为不可变的。
这个变体有点复杂,你可以像 Debojit Paul 提到的那样使用 dirtyMap.map(...).toMap
。
另一种变体是foldLeft
:
dirtyMap.foldLeft(Map[String, Set[String]]())(
(map, entry) => map + (entry._1 -> entry._2.toSet)
)
您指定累加器,即 immutable.Map
并使用转换后的集合将每个条目添加到此映射。
对于我来说,我认为使用 foldLeft
是更有效的方法。
您可以使用
dirtyMap.map({case (k,v) => (k,v.toSet)})
你可以简单地做:
dirtyMap.mapValues(_.toSet)
mapValues
只会将函数应用于 Map
的值,而 .toSet
会将可变的 Set
转换为不可变的
(我假设 dirtyMap
是一个 collection.immutable.Map
。如果它是可变的,只需在最后添加 toMap
)
如果您不熟悉 lambda 的下划线语法,它是 shorthand for:
dirtyMap.mapValues(v => v.toSet)
现在,由于 ()
,您的第一个示例无法编译。 toMap
不带显式参数,但它带隐式参数。如果您希望自动推断隐式参数,只需删除 ()
.
第二个示例不起作用,因为 foreach
returns Unit
。这意味着 foreach
会执行副作用,但它不会 return 一个值。如果你想对一个值进行链式转换,切勿使用 foreach
,而是使用 map
。