将可变字符串集的映射转换为 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