如何将这个难看的一行代码转换成清晰的scala代码来理解呢?



嘿,伙计们,我有这个丑陋的东西:

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的语法糖。OptionflatMap方法返回另一个Option。要获得多个值,您应该从序列开始,因此第一行应该是map <- test.toSeq。这解释了第二个错误消息。

推导式中的第二行尝试使用flatMap访问keys。它可以通过两种方式解决。或者用val keys = map.keys替换它,这样mapflatMap都不涉及,或者在呼叫第三个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
flatmapmap的理解的一个约束是,它自始至终需要相同类型的枚举器(实际上是一个单子),首先确定哪种类型。在您的示例中,第一个枚举数Option,因此它期望map.keyskeys也是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

最新更新