Uniqus
Uniqus

Reputation: 574

Scala: matching a String against a List of Regex

I have a string, say var str = "hello, world" and a List of Regex patterns

val patterns = List(new Regex("hello, (.*)", "substr"), new Regex("hi, (.*)", "substr"))

How can I match str against these patterns? Now instead of using List of patterns I'm doing the following:

val pattern1 = new Regex("hello, (.*)", "substr")
val pattern2 = new Regex("hi, (.*)", "substr")
var someVar = "something"
var someVar2 = "something else"
str match {
    case pattern1(substr) => { someVar = substr; someVar2 = "someValue" }
    case pattern2(substr) => { someVar = substr; someVar2 = "someOtherValue" }

}

Appendix:

I forgot to mention one important thing: in fact there are several lists of patterns. And someVar2 takes its value depending on the list from which the first pattern match occurred. It does not matter for me whether to use nested lists like List(List(new Regex(...), new Regex(...), ...), List(new Regex(...), new Regex(...), ...)) or to use separate val for each list of patterns like val patterns1 = List(new Regex(...), ...); val patterns2 = List(new Regex(...), ...).

Upvotes: 2

Views: 3798

Answers (2)

Shadowlands
Shadowlands

Reputation: 15074

Try this:

scala> patterns.collectFirst{ p => str match { case p(substr) => substr } }
res3: Option[String] = Some(world)

scala> val str2 = "hi, Fred"
str2: String = hi, Fred

scala> patterns.collectFirst{ p => str2 match { case p(substr) => substr } }
res4: Option[String] = Some(Fred)

EDIT: updating to account for changed requirements...

Given:

val patternMapping = Map(("marker1" -> patterns), ("marker2" -> patterns2), ...)

You should be able to nest the collectFirst calls, resulting in something like this:

scala> patternMapping.collectFirst{ case (mark, pList) => pList.collectFirst{ p => str match { case p(substr) => (mark -> substr) } } }.flatten
res5: Option[(String, String)] = Some((marker1,world))

I suspect this could probably be played around with and neatened up, but should give the general idea.

Upvotes: 7

Jatin
Jatin

Reputation: 31724

Well you yourself solved it. There are many ways. One of the idiomatic way is:

 val patterns = List(new Regex("hello, (.*)", "substr"), new Regex("hi, (.*)", "substr"))
 patterns.foreach{ x =>
   str match { 
          case x(substr) => { someVar = substr; someVar2 = "defaultValue" }
          case _ => ;     
       }
 }

In case, if you wish to replace defaultValue with the index of regex it matched then:

val  i = patterns.zipWithIndex
i.foreach{ x =>
       str match { 
              case x._1(substr) => { someVar = substr; someVar2 = "defaultValue - "+x._2 }
              case _ => ;     
           }
     }

Upvotes: 3

Related Questions