我有一个Map [String,Seq [String]],想要将其基本转换为Map [String,String],因为我知道序列只会有一个值。
我有一个Map [String,Seq [String]],想要将其基本转换为Map [String,String],因为我知道序列只会有一个值。
之前已经有人提到了mapValues
,但如果我是你的话,我会这样做:
scala> val m = Map(1 -> Seq(1), 2 -> Seq(2))
m: scala.collection.immutable.Map[Int,Seq[Int]] = Map(1 -> List(1), 2 -> List(2))
scala> m.map { case (k,Seq(v)) => (k,v) }
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1, 2 -> 2)
两个原因:
mapValues
方法生成结果 Map 的一个 视图,这意味着每次访问元素时都会重新计算函数。除非您计划仅访问每个元素一次,或者您只计划访问其中很小的一部分,否则您不希望进行重新计算。
使用带有 (k,Seq(v))
的 case 语句可以确保如果该函数看到一个不包含 恰好 一个元素的 Seq,则会抛出异常。使用 _(0)
或 _.head
将在没有元素时抛出异常,但如果有多个元素,则不会发出警告,这可能会导致后来出现神秘错误时缺少东西而没有错误。
mapValues()
函数。scala> Map("a" -> Seq("aaa"), "b" -> Seq("bbb"))
res0: scala.collection.immutable.Map[java.lang.String,Seq[java.lang.String]] = M
ap(a -> List(aaa), b -> List(bbb))
scala> res0.mapValues(_(0))
res1: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(a
-> aaa, b -> bbb)
.head
而不是(0)
是惯用语。 - om-nom-nom另一个建议:
m mapValues { _.mkString }
这段代码与 Seq 中是否有多个元素无关,它只是将所有字符串连接在一起。如果你担心每个值的重新计算,可以事先让它发生:
(m mapValues { _.mkString }).view.force
我认为我通过以下方式理解了它:
mymap.flatMap(x => Map(x._1 -> x._2.head))
map
(或其他专门的函数)可以更简单、更有效地完成。 - user166390