2012-10-01 29 views
0

我正在处理的Web应用程序的一部分处理需要绑定到模型(案例类)实例集合的表单。见this questionScala:批处理过程映射基于索引的表单域

所以,如果我一次添加多个用户,表单字段将命名为email[0]email[1]password[0]password[1]

发布形式导致Map[String, Seq[String]]

现在,我想要做的是按索引批量处理映射,以便每次迭代我都可以绑定一个User实例,创建一个List[User]作为绑定的最终结果。

我想到的被黑客入侵的方法是在Map键中对"[\d]"进行正则表达式匹配,然后通过过滤器或计数找到最高索引;通过表单字段的行数,然后(0..n).toList map{ ?? },相应地调用绑定/验证方法(这也需要Map[String, Seq[String]])。

什么是简单的方法来实现这一目标?

回答

1

假设:

  1. 所有地图键在形式"field[index]"
  2. 只有一个在Seq每个密钥值。
  3. 如果"email[x]"的条目比"password[x]"的条目多,反之亦然。

我会做这样的事情:

val request = Map(
    "email[0]" -> Seq("[email protected]"), 
    "email[1]" -> Seq("[email protected]"), 
    "password[0]" -> Seq("%vT*n7#4"), 
    "password[1]" -> Seq("Bfts7B&^") 
) 

case class User(email: String, password: String) 

val Field = """(.+)\[(\d+)\]""".r 

val userList = request.groupBy { case (Field(_, idx), _) => idx.toInt } 
         .mapValues { userMap => 
          def extractField(name: String) = 
           userMap.collect{case (Field(`name`, _), values) => values.head}.head 
          User(extractField("email"), extractField("password"))}  
         .toList.sortBy(_._1).map(_._2) 

// Exiting paste mode, now interpreting. 

request: scala.collection.immutable.Map[String,Seq[String]] = Map(email[0] -> List([email protected]), 
email[1] -> List([email protected]), password[0] -> List(%vT*n7#4), password[1] -> List(Bfts7B&^)) 
defined class User 
Field: scala.util.matching.Regex = (.+)\[(\d+)\] 
userList: List[User] = List(User([email protected],%vT*n7#4), User([email protected],Bfts7B&^)) 
+0

+1,美味。不清楚extractField位,需要抽象处理任何数量的字段的形式 - 这都是字符串,字符串地图,所以不应该是一个展示塞我不认为。 – virtualeyes

+0

应该提到表单binder/validator处理case类实例的创建,只需要将它作为Map [String,Seq [String]]传递给每个表单字段行,其余部分将被处理 – virtualeyes