Мульти-назначение на основе коллекции - PullRequest
4 голосов
/ 28 января 2012

Редактировать

Первоначально вопрос был «Коллекция в кортеж», так как я предполагал, что мне нужен кортеж для многократного назначения переменных. Оказывается, что многократное присваивание переменных можно выполнять непосредственно в коллекциях. Изменил вопрос соответственно.

Оригинал Имейте простой Seq [String], полученный из регулярного выражения, которое я хотел бы преобразовать в Tuple.

Какой самый прямой способ сделать это?

У меня сейчас есть:

val(clazz, date) = captures match {
  case x: Seq[String] => (x(0), x(1))
}

Это нормально, но у моего уровня маршрутизации есть несколько маршрутов с регулярным выражением, для которых я буду выполнять множественное назначение val (a, b, c) (группа перехвата всегда известна, поскольку маршрут не обрабатывается, если регулярное выражение не соответствует). Было бы неплохо иметь более простое решение, чем соответствие {case .. => ..}

Какой самый короткий однострочный конвертер для преобразования коллекций в кортежи в Scala?

Ответы [ 5 ]

5 голосов
/ 28 января 2012

Это не ответ на вопрос, но может решить проблему по-другому.

Вы знаете, что можете соответствовать xs: List[String], например, так:

val a :: b :: c :: _ = xs 

Это присваивает первые три элемента списка a,b,c? Вы можете сопоставить другие вещи, такие как Seq в объявлении val, как внутри оператора case. Убедитесь, что вы позаботились о соответствующих ошибках:

Перехват MatchError при инициализации val с сопоставлением с образцом в Scala?

3 голосов
/ 28 января 2012

Вы можете сделать это немного лучше, используя оператор |> от Scalaz.

scala> val captures = Vector("Hello", "World")
captures: scala.collection.immutable.Vector[java.lang.String] = Vector(Hello, World)

scala> val (a, b) = captures |> { x => (x(0), x(1)) }
a: java.lang.String = Hello
b: java.lang.String = World

Если вы не хотите использовать Scalaz, вы можете определить |> самостоятельно, как показано ниже:

scala> class AW[A](a: A) {
     |   def |>[B](f: A => B): B = f(a)
     | }
defined class AW

scala> implicit def aW[A](a: A): AW[A] = new AW(a)
aW: [A](a: A)AW[A]

EDIT:

Или что-то вроде предложения @ ziggystar:

scala> val Vector(a, b) = captures
a: java.lang.String = Hello
b: java.lang.String = World

Вы можете сделать его более кратким, как показано ниже:

scala> val S = Seq
S: scala.collection.Seq.type = scala.collection.Seq$@157e63a

scala> val S(a, b) = captures
a: java.lang.String = Hello
b: java.lang.String = World
2 голосов
/ 29 января 2012

Ваш вопрос изначально был специально о назначении отдельных групп захвата в регулярном выражении, которые уже позволяют вам назначать их непосредственно:

scala> val regex = """(\d*)-(\d*)-(\d*)""".r
regex: scala.util.matching.Regex = (\d*)-(\d*)-(\d*)

scala> val regex(a, b, c) = "29-1-2012"
d: String = 29
m: String = 1
y: String = 2012

очевидно, вы можете использовать их и в случае:

scala> "29-1-2012" match { case regex(d, m, y) => (y, m, d) }
res16: (String, String, String) = (2012,1,29)

, а затем сгруппируйте их по мере необходимости.

2 голосов
/ 28 января 2012

Как предложено @ziggystar в комментариях, вы можете сделать что-то вроде:

val (clazz, date) = { val a::b::_ = capture; (a, b)} 

или

val (clazz, date) = (capture(0), capture(1)) 

Если вы проверили тип списка, прежде чем он в порядке, но примитезаботиться о длине Seq, потому что код будет работать, даже если список имеет размер 0 или 1.

0 голосов
/ 29 января 2012

Последовательности для кортежа

Чтобы выполнить множественное назначение из Seq, как насчет следующего?

val Seq(clazz, date) = captures

Как видите, нет необходимости ограничивать List s;этот код выдаст MatchError, если длина не совпадает (в вашем случае это хорошо, потому что это означает, что вы допустили ошибку).Затем вы можете добавить

(clazz, date)

, чтобы воссоздать кортеж.

Кортежи из матчей

Однако Джед Уэсли-Смит опубликовал решение, которое позволяет избежать этой проблемы и решает оригиналвопрос лучше.В частности, в вашем решении есть Seq, длина которого не указана, поэтому, если вы допустите ошибку, компилятор не скажет вам;с кортежами вместо этого вам может помочь компилятор (даже если он не может проверить соответствие регулярному выражению).

...