Scala迭代地图并将单例列表转换为单例

时间:2013-12-12 22:58:44

标签: scala

我试图在Map中将类型List [T]的值提取为T。例如:

val c = Map(1->List(1), 2-> List(2), 3->List(3));

会变成

Map(1->1,2->2,3->3);

这是我到目前为止所写的内容:

val Some(values) = request.body.asFormUrlEncoded.foreach {
  case (key,value) =>
    Map(key->value.head);  
};

这是我收到的错误:

constructor cannot be instantiated to expected type; found : (T1, T2) required: scala.collection.immutable.Map[String,Seq[String]]

编辑:这就是这一行:

case (key,value) =>

EDIT2: request.body.asFormUrlEncoded示例输出

Some(Map(test -> List(324)))
Some(Map(SpO2 -> List(456), ETCO2 -> List(123)))

1 个答案:

答案 0 :(得分:4)

您确定列表中只有一个元素吗?如果是这样,你应该这样做,这是明确的,如果你偶然得到一个错误的列表(没有一个元素),它会产生错误。

c.map { case (k, List(v)) => k -> v }
// Map(1 -> 1, 2 -> 2, 3 -> 3)

如果您的列表可以包含多个元素,并且您只想要第一个元素,则可以执行此操作(这将在空列表中出错):

val d = Map(1 -> List(1), 2 -> List(2,4,6), 3 -> List(3))
d.map { case (k, List(v, _*)) => k -> v }
// Map(1 -> 1, 2 -> 2, 3 -> 3)

如果您的列表可能没有一个元素,并且您想忽略任何非单例列表而不是抛出错误,请使用collect代替map

val e = Map(1 -> List(1), 2 -> List(2,4,6), 3 -> List(3), 4 -> List())
e.collect { case (k, List(v)) => k -> v }
// Map(1 -> 1, 3 -> 3)

至于你的代码:

val Some(values) = request.body.asFormUrlEncoded.foreach {
  case (key,value) =>
    Map(key->value.head);  
};

这没有任何意义。

首先,foreach不会返回任何内容,因此将结果分配给变量将永远不会有效。您可能希望将其设为map,以便返回集合。

其次,您使用Some会让您看起来不理解Option,所以您可能想要了解它。

第三,如果你想让结果成为一个Map(一对对的集合),那么你只想返回一对key->value.head而不是Map。

第四,如果您在case (key,value)上遇到错误匹配,则可能asFormUrlEncoded实际上并未返回对的集合。你应该看看它的类型实际是什么。

最后,分号是不必要的。你应该删除它们。


根据您的评论

编辑

由于request.body.asFormUrlEncoded实际上会返回Some(Map("test" -> List(324)))之类的内容,因此以下是代码的外观。

如果asFormUrlEncoded可能会返回None,并且您无法处理该问题,那么您应该防范它:

val a = Some(Map("test" -> List(324)))
val value = a match {
  case Some(m) => m.collect { case (k, List(v)) => k -> v }
  case None => sys.error("expected something, got nothing")
}

如果您确定asFormUrlEncoded已经返回Some,那么您可以这样做:

val a = Some(Map("test" -> List(324)))
val Some(value) = a.map(_.collect { case (k, List(v)) => k -> v })