繁体   English   中英

为什么此scala fold返回等于类型?

[英]Why does this scala fold return Equals types?

我正试图在斯卡拉返回地图。 这是我的代码:

    val interestRegEx = """(\w+) Interests \((.+ Interest)\)""".r
    val singleAttributes = Seq("Sport Interests (Some Interest):Running,Swimming","Something else:True")
    val interests = singleAttributes.map { x =>
      // e.g. ("Sport Interests (Some Interest)", "Running,Swimming") should
      // result in ("Sport Running" -> "Some Interest", "Sport Swimming" -> "Some Interest")
      val attVal = x.split(':')

      attVal(0) match {
        case interestRegEx(interestProduct, interestAmount) =>
          Some(attVal(1).split(",").map { i =>
            Map(s"$interestProduct $i" -> interestAmount)
          }.reduce(_ ++ _))
        case _ => None
      }
    }.fold(Map[String, String]())(_) //.reduce(_ + _)

问题是试图将集合简化为单个Map [String,String]。 我以为折叠可能有用,但由于它也许根本不需要,所以以后甚至不需要添加reduce(_ + _) ,但这也不起作用。

我不了解的部分是IntelliJ告诉我interests类型为((Equals, Equals) => Equals) => Equals WTF? 这些Equals来自何处,为什么不将所有Maps加在一起以返回包含所有键和值的Map?

如果我们简化您的示例,我们将得到:

  val interests = Seq[String]().map { x =>
    Option[Map[String, String]](Map("k" -> "v"))
  }.fold(Map[String, String]())(_)

这意味着我们正在尝试将Seq[Option[Map[String, String]]] fold为初始值Map[String, String]()

def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)

fold定义中,我们可以看到编译器期望Option[Map[String, String]] (折叠中的每个值)和Map[String, String] (初始值)应为同一类型。

如果检查Option层次结构,将看到:

Option -> Product -> Equals

对于Map我们具有以下内容:

Map - > GenMap - > GenMapLike - > Equals (性状层次复杂,可能是另一个链存在)。

因此,我们可以看到最接近的常见类型是Equals

难题的第二部分是(_)

编译器将其视为lambda的参数:

val interests = x => /*omited*/.fold(Map[String, String]())(x)

我们看到x(A1, A1) => A1 在我们的例子中是:

(Equals, Equals) => Equals

fold Equals的结果是A1 ,它也Equals

因此,lambda类型为:

((Equals, Equals) => Equals) /*<< arg*/ => /*result >>*/ Equals

更新:

为了解决您的问题,我认为您应该使用:

.flatten.reduce(_ ++ _)

当您获得诸如ProductEquals的特征作为语句的推断类型时,通常可以打赌您在某些高阶函数中类型不匹配。 通常不会得到AnyAnyRef因为只有在某些类型的集合没有共同之处时才会发生。 我想知道的一件事是,您的fold的第二个参数仅采用一个参数。 足够令人惊讶的是,它进行了类型检查,但这可能是为您提供了您所不期望的类型的原因。

我认为您想做的更像是:

val interestRegEx = """(\w+) Interests \((.+ Interest)\)""".r
val singleAttributes = Seq("Sport Interests (Some Interest):Running,Swimming","Something else:True")
val interests = singleAttributes.map { x =>
  // e.g. ("Sport Interests (Some Interest)", "Running,Swimming") should
  // result in ("Sport Running" -> "Some Interest", "Sport Swimming" -> "Some Interest")
  val attVal = x.split(':')

  attVal(0) match {
    case interestRegEx(interestProduct, interestAmount) =>
      attVal(1).split(",").map { i =>
        Map(s"$interestProduct $i" -> interestAmount)
      }.reduce(_ ++ _)
    case _ => Map.empty
  }
}.reduce(_ ++ _)

为此,我得到了:

scala> interests
res0: scala.collection.immutable.Map[_ <: String, String] = Map(Sport Running -> Some Interest, Sport Swimming -> Some Interest)

我摆脱了在您的正则表达式匹配中包装MapOption 由于您打算合并地图,因此最好将空白地图用作不匹配的情况。 然后,就像您在内部map所做的一样,我使用reduce而不是fold来进行最终比赛。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM