【问题标题】:Convert Map of mutable Set of strings to Map of immutable set of strings in Scala在 Scala 中将可变字符串集映射转换为不可变字符串集映射
【发布时间】:2018-06-15 04:57:11
【问题描述】:

我有一个“dirtyMap”,它是不可变的。Map[String, collection.mutable.Set[String]]。我想将dirtyMap 转换为不可变的Map[String, Set[String]]。你能否让我知道如何做到这一点。我尝试了几种没有产生积极结果的方法

方法一:使用地图功能

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 的回答

【问题讨论】:

  • 在方法1中删除toMap之后的括号也有助于消除语法错误。

标签: scala scala-collections


【解决方案1】:

你可以这样做:

dirtyMap.mapValues(_.toSet)

mapValues 将只将函数应用于Map 的值,.toSet 将可变的Set 转换为不可变的。

(我假设dirtyMap 是collection.immutable.Map。如果它是可变的,只需在最后添加toMap)

如果您不熟悉 lambda 的下划线语法,它是以下划线的简写:

dirtyMap.mapValues(v => v.toSet)

现在,由于(),您的第一个示例无法编译。 toMap 不接受显式参数,但它接受隐式参数。如果您希望自动推断隐式参数,只需删除 ()。

第二个例子不起作用,因为foreach 返回Unit。这意味着foreach 执行副作用,但不返回值。如果你想对一个值进行链式转换,千万不要使用foreach,而是使用map。

【讨论】:

    【解决方案2】:

    你可以使用

    dirtyMap.map({case (k,v) => (k,v.toSet)})

    【讨论】:

    • 它仍然返回mutable.Map。需要toMap
    • scala> dirtyMap.map({case (k,v) => (k,v.toSet)}) res2: scala.collection.immutable.Map[String,scala.collection.immutable.Set[String]] = Map(a -> Set(3, 1, 2), b -> Set(3, 1, 2))
    • 你确定你的dirtyMap是immutable吗?
    • 尝试执行我不知道你为什么说它会返回可变映射。请分享您的输出
    • scala> val dirtyMap = new mutable.HashMap[String, collection.mutable.Set[String]] () dirtyMap: scala.collection.mutable.HashMap[String,scala.collection.mutable.Set[String]] = Map() scala> dirtyMap update ("test1", collection.mutable.Set("test11", "test12")) scala> dirtyMap update ("test2", collection.mutable.Set("test21", "test22")) scala> dirtyMap.map({case (k,v) => (k,v.toSet)}) res2: scala.collection.mutable.HashMap[String,scala.collection.immutable.Set[String]] = Map(test2 -> Set(test21, test22), test1 -> Set(test12, test11))
    【解决方案3】:

    您可以使用flatMap:

    dirtyMap.flatMap(entry => Map[String, Set[String]](entry._1 -> entry._2.toSet)).toMap
    

    首先你 map 每个条目到 immutable.Map(entry) 更新条目,现在值是 immutable.Set。您的地图如下所示:mutable.Map。 然后flatten 被调用,所以你得到mutable.Map 与immutable.Set 的每个条目。然后 toMap 将此映射转换为不可变的。

    这个变种有点复杂,你可以像 Debojit Paul 提到的那样简单地使用dirtyMap.map(...).toMap。

    另一个变种是foldLeft:

    dirtyMap.foldLeft(Map[String, Set[String]]())(
      (map, entry) => map + (entry._1 -> entry._2.toSet)
    )
    

    您指定累加器,即immutable.Map,并使用转换后的 Set 将每个条目添加到此映射。

    对于我来说,我认为使用foldLeft 是更有效的方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-06
      • 2019-08-12
      • 1970-01-01
      • 2013-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多