Angenommen, ich habe ein Regex-Muster, dem ich viele Strings zuordnen möchte.
val Digit = """\d""".r
Ich möchte nur überprüfen, ob ein bestimmter String vollständig mit dem Regex übereinstimmt. Was ist ein guter und idiomatischer Weg, dies in Scala zu tun?
Ich weiß, dass ich Muster-Übereinstimmungen mit Regexes erstellen kann, aber dies ist syntaktisch in diesem Fall nicht sehr erfreulich, da ich keine Gruppen zum Extrahieren habe:
scala> "5" match { case Digit() => true case _ => false }
res4: Boolean = true
Oder ich könnte auf das zugrunde liegende Java-Muster zurückgreifen:
scala> Digit.pattern.matcher("5").matches
res6: Boolean = true
das ist auch nicht elegant.
Gibt es eine bessere Lösung?
"5" match { case Digit() => true case _ => false }
sieht besser aus als das zugrunde liegende Musterobjekt zu verwenden.Antworten:
Bei der Beantwortung meiner eigenen Frage verwende ich das Muster "Zuhälter meiner Bibliothek".
object RegexUtils { implicit class RichRegex(val underlying: Regex) extends AnyVal { def matches(s: String) = underlying.pattern.matcher(s).matches } }
und benutze es so
import RegexUtils._ val Digit = """\d""".r if (Digit matches "5") println("match") else println("no match")
es sei denn, jemand findet eine bessere (Standard-) Lösung.
Anmerkungen
Ich habe nicht gepimpt
String
, um den Umfang möglicher Nebenwirkungen einzuschränken.unapplySeq
liest sich in diesem Zusammenhang nicht sehr gut.quelle
String
stattdessen gepimpt , und das funktioniert bisher trotz derString
Mitgliedsfunktion einwandfreimatches(regex: String)
.misses
gepimpt. Match und Missmatch :-) Es ist so nervig,!s.matches(r)
statt schreiben zu müssens misses r
. Hmm"5" matches "\\d"
@polygenelubricants vorgeschlagen?case r(_*) =>
.Ich kenne Scala nicht so gut, aber es sieht so aus, als ob Sie einfach Folgendes tun können:
"5".matches("\\d")
Verweise
quelle
.pattern.matcher(text).matches
der richtige Weg bist . Sie können die Ausführlichkeit unter einer Dienstprogrammmethode oder einem überladenen Operator oder etwas anderem ausblenden, wenn Scala dies unterstützt.Für die vollständige Übereinstimmung können Sie unapplySeq verwenden . Diese Methode versucht, das Ziel (ganze Übereinstimmung) abzugleichen und gibt die Übereinstimmungen zurück.
scala> val Digit = """\d""".r Digit: scala.util.matching.Regex = \d scala> Digit unapplySeq "1" res9: Option[List[String]] = Some(List()) scala> Digit unapplySeq "123" res10: Option[List[String]] = None scala> Digit unapplySeq "string" res11: Option[List[String]] = None
quelle
case
s einesmatch
Blocks."""\d""".r.unapplySeq("5").isDefined //> res1: Boolean = true """\d""".r.unapplySeq("a").isDefined //> res2: Boolean = false
quelle
Die Antwort ist in der Regex:
val Digit = """^\d$""".r
Verwenden Sie dann eine der vorhandenen Methoden.
quelle
String/Pattern/Matcher.matches
Zumindest in Java stimmt die gesamte Zeichenfolge bereits überein. Ich denke, das Problem ist nur Stil / Redewendung für Regexing in Scala, dh was diese "eine der vorhandenen Methoden" sind.Matcher.matches
ist eine Aberration. Ok, es macht einige Optimierungen möglich, obwohl ich nicht weiß, ob die Java-Bibliothek tatsächlich davon profitiert. Die Standardmethode für reguläre Ausdrücke, um auszudrücken, dass eine vollständige Übereinstimmung erforderlich ist, ist die Verwendung von Ankern. Da die Scala Bibliothek ist nicht bietet eine vollständige Match - Methode, dann dem richtigen Weg , es zu tun ist , Anker zu verwenden. Entweder das, oder Sie verwenden die Java-Bibliothek.matches
, aber ok. WasOption
vs betrifftBoolean
, fügenonEmpty
es am Ende hinzu und du bekommst dasBoolean
.Verwenden der Standard-Scala-Bibliothek und eines vorkompilierten Regex-Musters und Musterabgleichs (Stand der Technik):
val digit = """(\d)""".r "2" match { case digit( a) => println(a + " is Digit") case _ => println("it is something else") }
mehr zu lesen: http://www.scala-lang.org/api/2.12.1/scala/util/matching/index.html
quelle