Scala: пакетный процесс Карта полей формы на основе индекса

Часть веб-приложения, над которым я работаю, обрабатывает формы, которые необходимо привязать к коллекции экземпляров модели (класса случая). См. этот вопрос

Итак, если бы я добавил несколько пользователей одновременно, поля формы были бы названы email[0], email[1], password[0], password[1] и т. д.

Публикация формы приводит к Map[String, Seq[String]]

Теперь то, что я хотел бы сделать, это обрабатывать карту партиями по индексу, чтобы для каждой итерации я мог привязывать экземпляр пользователя, создавая List[User] в качестве конечного результата привязок.

Взломанный подход, о котором я думаю, состоит в том, чтобы сопоставить регулярное выражение с "[\d]" в ключах карты, а затем найти самый высокий индекс с помощью фильтра или подсчета; с этим, затем (0..n).toList map{ ?? } через количество строк поля формы, вызывая метод привязки/проверки (который также принимает Map[String, Seq[String]]) соответственно.

Каков краткий способ добиться этого?


person virtualeyes    schedule 01.10.2012    source источник


Ответы (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&^))
person incrop    schedule 01.10.2012
comment
+1, вкусно. Не уверен насчет бита extractField, который необходимо абстрагировать от обработки форм любого количества полей - это все String, String Maps, так что я не думаю, что это должно быть препятствием для показа. - person virtualeyes; 01.10.2012
comment
следует упомянуть, что связующее/валидатор формы обрабатывает создание экземпляра класса case, просто нужно передать ему каждую строку поля формы как Map[String, Seq[String]], об остальном позаботятся - person virtualeyes; 01.10.2012