Is there a good way to test a string against a ser...
# announcements
n
Is there a good way to test a string against a series of regex without matching twice? Right now I have
Copy code
for (line in lines) {
   if (Regex("#(.) A (.+)").matches(line)) {
       val m = Regex("#(.) A (.+)").matchEntire(line)
        ...
   } else if (Regex("#(.) B (.+)").matches(line)) {
       val m = Regex("#(.) B (.+)").matchEntire(line)
       ...
   }
}
(real code of course has regexes defined only once etc.). I now changed it to
Copy code
for (line in lines) {
   val m1 = Regex("#(.) A (.+)").matchEntire(line)
   if (m1 != null) {
      ...
      continue
   }
   val m2 = Regex("#(.) B (.+)").matchEntire(line)
   if (m2 != null) {
      ...
      continue
   }
}
but that does not look too nice (esp. the need for repeated
continue
)
n
can you edit in more newlines? it's kinda impossible to read
but also
matchEntire
already returns null if there's no match
...and also you're constructing each Regex object from scratch for every line
n
Regex from scratch: that is just here to keep the sample smaller. Real code has that extracted.
Ideally I would like to have a
when
which understands regex and injects the MatchResult into the block
Copy code
when (line) {
   Regex("A(.+)") -> println(it.groupValues[1])
    Regex("B(.)(.+)") -> println(it.groupValues[2])
}
(i.e. here
it
would refer to the MatchResult)
n
sounds Perl/Ruby-ish 🙂 running through some examples in my head...I don't think you can avoid a continue. if you use pattern.match()?.let, you'd need a continue
there might be some
sequenceOf({ performMatch }).firstNotNull()
trickery you could do but I don't think it's worth it
n
It really depends how much you care, I thought about this problem a bit before when i was comparing python and kotlin, and looking at walrus operator use cases in python, one of the examples was similar to this
If you care enough then you can write a function that would do something like this:
Copy code
firstMatchEntire(line,
    Regex("#(.) A (.+)") to { .... },
    Regex(...) to { ... }
)
and so on
n
also, might not be possible, but perhaps you can simply combine the regexes into one larger regex
e
this is possible:
Copy code
regex1.matchEntire(line)?.also { match ->
} ?: regex2.matchEntire(line)?.also { match ->
} ?: regex3.matchEntire(line)?.also { match ->
} // etc.
this is a case where Scala's pattern matching and destructuring works well, but it needs more design work to get into Kotlin. https://youtrack.jetbrains.com/issue/KT-186