我有一个" dirtyMap"这是immutable.Map [String,collection.mutable.Set [String]]。我想将dirtyMap转换为不可变Map [String,Set [String]]。你能告诉我怎么做吗?我尝试了几种没有产生积极结果的方法
方法1:使用地图功能
dirtyMap.toSeq.map(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
我收到语法错误
方法2:使用foreach
dirtyMap.toSeq.foreach(e => {
val key = e._1
val value = e._2.to[Set]
e._1 -> e._2
}).toMap()
无法将地图应用于foreach的输出
免责声明:如果你不能告诉我,我是Scala noob。
更新:当我从toMap()函数中删除括号时,方法1有效。但是,以下是一个优雅的解决方案
dirtyMap.mapValues(v => v.toSet)
感谢Gabriele提供了一个很好的解释。感谢Duelist和Debojit的回答
答案 0 :(得分:1)
您可以这样做:
dirtyMap.mapValues(_.toSet)
mapValues
会将该函数仅应用于Map
的值,而.toSet
会将可变Set
转换为不可变的值。{/ p>
(我假设dirtyMap
是collection.immutable.Map
。如果它是可变的,只需在最后添加toMap
如果你不熟悉lambdas的下划线语法,那么它是一个简写:
dirtyMap.mapValues(v => v.toSet)
现在,由于()
,您的第一个示例无法编译。 toMap
没有明确的参数,但它需要一个隐含的参数。如果您希望自动推断隐式参数,只需删除()
。
第二个示例不起作用,因为foreach
返回Unit
。这意味着foreach
执行副作用,但它不返回值。如果您想对值进行变换,请不要使用foreach
,而是使用map
。
答案 1 :(得分:0)
您可以使用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将此映射转换为不可变的。
这个版本有点复杂,你只需使用dirtyMap.map(...).toMap
作为Debojit Paul提到的。
另一个变体是foldLeft
:
dirtyMap.foldLeft(Map[String, Set[String]]())(
(map, entry) => map + (entry._1 -> entry._2.toSet)
)
指定累加器,即immutable.Map
,并使用转换后的Set将每个条目添加到此地图。
至于我,我认为使用foldLeft
是更有效的方式。
答案 2 :(得分:0)
您可以使用
dirtyMap.map({case(k,v)=>(k,v.toSet)})