如何在Seq [A]中正确映射元组函数?

时间:2013-07-29 01:00:40

标签: scala map tuples sequence

我有一个函数正在尝试构建一个JSON对象,该对象包含存储在Seq[A]中的多个元组的表示,其中A(Loop, Option[User])。我的代码看起来像这样:

def loops = Action {
    val page : Int = 1
    val orderBy : Int = 1
    val filter : String = ""
    val jsonifyLoops : (Loop, Option[User]) => Map[String, String] = { 
      case (loop,user) =>
            Map(
                "name" -> loop.name,
                "created_at" -> loop.createdAt.map(dateFormat.format).getOrElse(""),
                "deleted_at" -> loop.deletedAt.map(dateFormat.format).getOrElse(""),
                "user_name" -> user.map(_.name).getOrElse("")
            )
    }
    Ok(toJson(Map(
        "loops" -> toJson(
            Loop.list( page = page, orderBy = orderBy, filter = ("%"+filter+"%") )
                .items.map( jsonifyLoops )
            )
        )
    ))
}

Loops.list从下面的助手类产生Page[A]

case class Page[A](items: Seq[A], page: Int, offset: Long, total: Long) {
    lazy val prev = Option(page - 1).filter(_ >= 0)
    lazy val next = Option(page + 1).filter(_ => (offset + items.size) < total)
}

因此,Loops.list(...).items应该为我Seq[(Loop, Option[User])],我应该能够应用地图功能。我已经定义了我的jsonifyLoops函数以获得我认为合适的原型,但我必须做错了,因为编译器会抛出以下错误:

    [error] [...] Application.scala:42: type mismatch;
    [error]  found   : (models.Loop, Option[models.User]) => Map[String,String]
    [error]  required: (models.Loop, Option[models.User]) => ?
    [error]                     .items.map( jsonifyLoops )
    [error]                                 ^

我做错了什么?

2 个答案:

答案 0 :(得分:2)

您的函数jsonifyLoops有两个参数:LoopOption[User]。但是,items的成员是(Loop, Option[User])类型的元组,因此items.map需要一个接受该元组的参数作为参数。因此,您需要将jsonifyLoops从二进制函数转换为带有一对参数的一元函数; Function2#tupled会为您执行此操作:

scala> :t jsonifyLoops
(Loop, Option[User]) => Map[String,String]
scala> :t jsonifyLoops.tupled
((Loop, Option[User])) => Map[String,String]

你会这样使用它:

Loop.list(page = page, orderBy = orderBy, filter = ("%"+filter+"%"))
    .items.map(jsonifyLoops.tupled)

答案 1 :(得分:1)

您需要在jasonifyLoops中为模式匹配添加默认大小写。 如果没有默认情况,如果您的案例陈述失败,则返回一个单位。 所以这样的事情应该有效:

val jsonifyLoops : (Loop, Option[User]) => Map[String, String] = { 
  case (loop,user) =>
        Map(
            "name" -> loop.name,
            "created_at" -> loop.createdAt.map(dateFormat.format).getOrElse(""),
            "deleted_at" -> loop.deletedAt.map(dateFormat.format).getOrElse(""),
            "user_name" -> user.map(_.name).getOrElse("")
        )
  case _ => Map[String, String]()
}

这只是说如果输入不匹配,则返回一个空的Map。但是,您应该将此替换为您要对默认情况执行的任何处理。