ovgolovin
ovgolovin

Reputation: 13410

Unpack all groups from regex match

There is a very nice way to unpack matched groups from regex:

scala> val regex = "(first):(second)".r
regex: scala.util.matching.Regex = (first):(second)

scala> val regex(a, b) = "first:second"
a: String = first
b: String = second

Unfortunately, this throws exception when there is no match:

scala> val regex(a, b) = "first:third"
scala.MatchError: first:third (of class java.lang.String)
        at .<init>(<console>:10)
        at .<clinit>(<console>)
        at .<init>(<console>:11)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
        at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
        at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
        at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
        at java.lang.Thread.run(Thread.java:744)

In this case I could use findFirstMatchIn to get None is there is no match:

scala> val result = regex.findFirstMatchIn("first:third")
result: Option[scala.util.matching.Regex.Match] = None

But in case of match, I want to have something as good as the first variant with unpacking. Now I have to deal with this:

scala> val result = regex.findFirstMatchIn("first:second")
result: Option[scala.util.matching.Regex.Match] = Some(first:second)

What I came up with is this:

scala> val content = result.get
content: scala.util.matching.Regex.Match = first:second

scala> 1 to content.groupCount map content.group
res0: scala.collection.immutable.IndexedSeq[String] = Vector(first, second)

Is there any better way to get all groups from regex match object (ideally as succinct as unpacking in the first code snippet in this question)?

Upvotes: 0

Views: 606

Answers (2)

ccheneson
ccheneson

Reputation: 49410

You could use pattern matching

Something along this (untested)

val regex = "(first):(second)".r
val myString = "first:second"
myString  match {
    case regex(first, second) => do something
    case _ => None
}

Upvotes: 1

som-snytt
som-snytt

Reputation: 39577

They came up with Groups for that:

scala> regex findFirstMatchIn "first:second" map { case Regex.Groups(a,b) => (a,b) }
res8: Option[(String, String)] = Some((first,second))

I think that's the same now as:

scala> regex findFirstMatchIn "first:second" map { case regex(a,b) => (a,b) }
res9: Option[(String, String)] = Some((first,second))

since it doesn't recompute the match.

Upvotes: 3

Related Questions