嘿,伙计们,我有这个丑陋的东西:
val test = Some(Map("TesT",123))
val keys = test.getOrElse(Map()).keys.map(_.toLowerCase).asInstanceOf[Set[String]]
require(keys.contains("test")
我能把它(第2行)变成一个干净/可读的理解吗?
这是我的尝试:
scala> val keys = for {
| map <- test
| keys <- map.keys
| k <- keys
| } yield k.toLowerCase
<console>:18: error: value toLowerCase is not a member of Char
} yield k.toLowerCase
^
<console>:16: error: type mismatch;
found : Iterable[Char]
required: Option[?]
keys <- map.keys
^
您不需要理解这个。清楚地对操作进行排序,并明确地拼写步骤,通常更清晰易读。只是不要试图把所有内容塞进一行:
test
.iterator
.flatMap(_.keys)
.map(_.toLowerCase)
.contains("test")
推导式只是map
/flatMap
的语法糖。Option
的flatMap
方法返回另一个Option
。要获得多个值,您应该从序列开始,因此第一行应该是map <- test.toSeq
。这解释了第二个错误消息。
推导式中的第二行尝试使用flatMap
访问keys
。它可以通过两种方式解决。或者用val keys = map.keys
替换它,这样map
或flatMap
都不涉及,或者在呼叫第三个k <- map.keys
时完全删除这一行。这将修复第一个错误。
所以你可以在两个解决方案中选择:
val keys = for {
map <- test.toSeq
val keys = map.keys
k <- keys
} yield k.toLowerCase
或
val keys = for {
map <- test.toSeq
k <- map.keys
} yield k.toLowerCase
原文:
val keys = for {
map <- test
keys <- map.keys
k <- keys
} yield k.toLowerCase
对flatmap
和map
的理解的一个约束是,它自始至终需要相同类型的枚举器(实际上是一个单子),首先确定哪种类型。在您的示例中,第一个枚举数是Option
,因此它期望map.keys
和keys
也是Option
类型。你的例子的另一个问题是,keys
实际上是一个单独的key
从集合map.keys
…因此,k
将在keys: String
中引用枚举数中的字符。
通过将for
推导式的初始类型转换为Seq
来解决for-comprehension类型问题,允许以下术语属于该类型(它们是),然后在提取key
后停止:
val keys = for {
map <- test.toSeq
key <- map.keys
} yield key.toLowerCase