0

私が取り組んでいるWebアプリの一部は、モデル(ケースクラス)インスタンスのコレクションにバインドする必要があるフォームを処理します。この質問を参照してください

したがって、一度に複数のユーザーを追加する場合、フォームフィールドには、、、、などの名前が付けemail[0]られます。email[1]password[0]password[1]

フォームを投稿すると、Map[String, Seq[String]]

ここで、マップをインデックスごとにバッチで処理して、反復ごとにUserインスタンスをバインドし、List[User]バインドの最終結果としてを作成できるようにします。

私が考えているハッキングされたアプローチは"[\d]"、マップキーで正規表現の一致を確認し、フィルターまたはカウントを介して最高のインデックスを見つけることです。それで、フォームフィールドの行の数を介して、それに応じ(0..n).toList map{ ?? }てバインディング/検証メソッド(これもMap[String, Seq[String]])を呼び出します。

これを達成するための簡潔な方法は何ですか?

4

1 に答える 1

1

仮定して:

  1. すべてのマップキーはフォームにあります"field[index]"
  2. Seq各キーの値は1つだけです。
  3. のエントリがある場合は、のエントリがある場合"email[x]""password[x]"またはその逆の場合。

私はこのようなことをします:

val request = Map(
  "email[0]" -> Seq("alice@example.com"),
  "email[1]" -> Seq("bob@example.com"),
  "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(alice@example.com), 
email[1] -> List(bob@example.com), password[0] -> List(%vT*n7#4), password[1] -> List(Bfts7B&^))
defined class User
Field: scala.util.matching.Regex = (.+)\[(\d+)\]
userList: List[User] = List(User(alice@example.com,%vT*n7#4), User(bob@example.com,Bfts7B&^))
于 2012-10-01T13:37:28.047 に答える