Collection Based Multitasking

Edit

the original question was “Collection to Tuple”, as I suggested that I needed a tuple to do multitasking. It turns out that you can perform variable multi-assignment directly in collections. Edit the question accordingly.

Original Have a simple Seq [String] derived from a regular expression that I would like to convert to Tuple.

What is the most direct way to do this?

I currently have:

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

This is normal, but my routing level has many routes matched by the regex, which I will perform with multiple assignments val (a, b, c) (the capture group is always known, since the route is not processed if the regex does not match). It would be nice to have a more compact solution than a match {case .. => ..}

What is the shortest 1-line file for converting collections to tuples in Scala?

+4
source share
5 answers

This is not an answer to the question, but can solve the problem differently.

You know that you can map xs: List[String] like this:

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

Does this assign the first three elements of the list a,b,c ? You can map other things, such as Seq in the val declaration, as well as inside the case . Be sure to observe the relevant errors:

Catching MatchError when initializing val with matching patterns in Scala?

+5
source

You can do this a little better by using the |> operator from 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 

If you do not want to use Scalaz, you can define |> yourself, as shown below:

 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:

Or, something like the @ziggystar suggestion:

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

You can make it more concise, as shown below:

 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 
+3
source

As suggested by @ziggystar in the comments, you can do something like:

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

or

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

If you checked the type of the list before it’s OK, but take care of the length of Seq , because the code will work even if the list is 0 or 1 in size.

+2
source

Initially, your question is related to the assignment of individual capture groups in the regular expression, which already allow you to directly assign them:

 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 

obviously, you can use them in the case of:

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

and then group them as needed.

+2
source

Tuple sections

To do multitasking from Seq , how about the following?

 val Seq(clazz, date) = captures 

As you can see, there is no need to limit List s; this code will MatchError if the length does not match (in your case, this is good because it means you made a mistake). Then you can add

 (clazz, date) 

to recreate the tuple.

Tuples of matches

However, Jed Wesley-Smith published a solution that avoids this problem and better solves the original issue. In particular, in your solution you have Seq, the length of which is not specified, therefore, if you make a mistake, the compiler will not tell you; with tuples, the compiler can help you instead (even if it cannot validate the regular expression).

0
source

Source: https://habr.com/ru/post/1393508/


All Articles