2012-10-01 24 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