从列表选项创建映射

Cok*_*aka 6 scala list-comprehension

我正在尝试从列表选项中创建一个地图.所以,我有一个像这样声明的列表选项:

val authHeaders: Option[Set[String]] = Some(Set("a", "b", "c"))

我想得到这样的地图:(a - > a,b - > b,c - > c).

所以我尝试了这种方式:

for {
  headers <- authHeaders
  header <- headers
} yield (header -> header)
Run Code Online (Sandbox Code Playgroud)

但我得到这个错误:

<console>:11: error: type mismatch;
found   : scala.collection.immutable.Set[(String, String)]
required: Option[?]
             header <- headers
                    ^
Run Code Online (Sandbox Code Playgroud)

我哪里做错了?

补充说明:这个选项让我非常头疼,但我需要了解如何在任何情况下处理它.无论如何,仅仅为了比较,我尝试通过删除选项来消除头痛因素.

scala> val bah = Set("a", "b", "c")
bah: scala.collection.immutable.Set[String] = Set(a, b, c)

scala> (
     | for {
     | x <- bah
     | } yield (x -> x)).toMap
res36: scala.collection.immutable.Map[String,String] = Map(a -> a, b -> b, c -> c)
Run Code Online (Sandbox Code Playgroud)

所以,显然它有效.这有什么区别?

附加说明:

在这里看起来像"for comprehension"的游戏规则:如果它产生了某些东西,那么某些东西必须与外部集合的类型相同(在这种情况下是authHeaders,它是一个Option [?]).如何解决它?

谢谢!,拉卡

Kig*_*gyo 8

问题

for被骗了:

authHeaders.flatMap(headers => headers.map(header => header -> header))
Run Code Online (Sandbox Code Playgroud)

在这种情况下的问题是使用flatMap,因为authHeadersOption.
让我们来看看签名.(http://www.scala-lang.org/api/2.11.1/index.html#scala.Option)

final def flatMap[B](f: (A) ? Option[B]): Option[B]
Run Code Online (Sandbox Code Playgroud)

所以函数f有望返回Option.但authHeaders.map(header => header -> header)不是一个Option因此你得到一个错误.

一个办法

假设,如果authHeadersNone你想要一个空的Map,我们就可以使用fold.

authHeaders.fold(Map.empty[String, String])(_.map(s => s -> s).toMap)
Run Code Online (Sandbox Code Playgroud)

第一个参数是结果,如果authHeadersNone.第二个预计是一个函数Set[String] => Map[String, String],如果有的话会得到评估Set.

如果你想把结果保存在一个Option只想有一个Map实际存在的时候Set,你可以简单地使用map.

authHeaders.map(_.map(s => s -> s).toMap)
Run Code Online (Sandbox Code Playgroud)

关于你的附加说明

这是flatMapon 的签名TraversableOnce.(http://www.scala-lang.org/api/2.11.1/index.html#scala.collection.TraversableOnce)

def flatMap[B](f: (A) ? GenTraversableOnce[B]): TraversableOnce[B]
Run Code Online (Sandbox Code Playgroud)

这里f可以返回任何实例的集合GenTraversableOnce.

所以这样的事情是可能的:( Set(1,2,3).flatMap(i => List(i))不是真正的创造性例子,我知道..)

我认为这Option是一个特例.