简体   繁体   中英

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(...), ...) val patterns1 = List(new Regex(...), ...); val patterns2 = List(new Regex(...), ...) .

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.

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 _ => ;     
           }
     }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM