Załóżmy, że mam wzór Regex, do którego chcę dopasować wiele ciągów.
val Digit = """\d""".r
Chcę tylko sprawdzić, czy dany ciąg w pełni pasuje do wyrażenia regularnego. Jaki jest dobry i idiomatyczny sposób na zrobienie tego w Scali?
Wiem, że mogę dopasować wzorce na Regexes, ale w tym przypadku nie jest to zbyt przyjemne, ponieważ nie mam grup do wyodrębnienia:
scala> "5" match { case Digit() => true case _ => false }
res4: Boolean = true
Albo mogę wrócić do podstawowego wzorca Java:
scala> Digit.pattern.matcher("5").matches
res6: Boolean = true
co też nie jest eleganckie.
Czy jest lepsze rozwiązanie?
"5" match { case Digit() => true case _ => false }
wygląda lepiej niż użycie podstawowego obiektu wzorca.Odpowiedzi:
Odpowiadając na własne pytanie, użyję wzoru „odpicuj moją bibliotekę”
object RegexUtils { implicit class RichRegex(val underlying: Regex) extends AnyVal { def matches(s: String) = underlying.pattern.matcher(s).matches } }
i używaj go w ten sposób
import RegexUtils._ val Digit = """\d""".r if (Digit matches "5") println("match") else println("no match")
chyba że ktoś wymyśli lepsze (standardowe) rozwiązanie.
Uwagi
Nie starałem
String
się ograniczyć zakresu potencjalnych skutków ubocznych.unapplySeq
nie czyta zbyt dobrze w tym kontekście.źródło
String
Zamiast tego pimpedowałem i jak dotąd działa to dobrze, pomimoString
funkcji członkamatches(regex: String)
.misses
. Match and missmatch :-) To takie irytujące, że trzeba pisać!s.matches(r)
zamiast pisaćs misses r
. Hmm"5" matches "\\d"
który zasugerował @polygenelubricants?case r(_*) =>
.Nie znam Scali aż za dobrze, ale wygląda na to, że możesz po prostu zrobić:
"5".matches("\\d")
Bibliografia
źródło
.pattern.matcher(text).matches
jest droga. Możesz ukryć gadatliwość pod jakąś metodą narzędzia lub przeciążonym operatorem lub czymś podobnym, jeśli Scala to obsługuje.Aby uzyskać pełne dopasowanie, możesz użyć unapplySeq . Ta metoda próbuje dopasować cel (całe dopasowanie) i zwraca dopasowania.
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
źródło
case
smatch
bloku."""\d""".r.unapplySeq("5").isDefined //> res1: Boolean = true """\d""".r.unapplySeq("a").isDefined //> res2: Boolean = false
źródło
Odpowiedź znajduje się w wyrażeniu regularnym:
val Digit = """^\d$""".r
Następnie użyj jednej z istniejących metod.
źródło
String/Pattern/Matcher.matches
, przynajmniej w Javie, jest już dopasowany cały ciąg. Myślę, że chodzi tylko o styl / idiom dla regexingu w Scali, czyli czym jest ta „jedna z istniejących metod”.Matcher.matches
to aberracja. Ok, umożliwia to pewne optymalizacje, chociaż nie wiem, czy biblioteka Java faktycznie to wykorzystuje. Ale standardowym sposobem wyrażenia w wyrażeniach regularnych, że wymagane jest pełne dopasowanie, jest użycie kotwic. Ponieważ biblioteka Scala nie zapewnia metody pełnego dopasowania, właściwym sposobem jest użycie kotwic. Albo to, albo skorzystaj z biblioteki Java.matches
, ale ok. Jeśli chodzi oOption
vsBoolean
, dodajnonEmpty
do końca, a otrzymaszBoolean
.Korzystanie z biblioteki Standard Scala i wstępnie skompilowanego wzorca wyrażenia regularnego i dopasowania do wzorca (co jest najnowocześniejszym standardem Scala):
val digit = """(\d)""".r "2" match { case digit( a) => println(a + " is Digit") case _ => println("it is something else") }
więcej do przeczytania: http://www.scala-lang.org/api/2.12.1/scala/util/matching/index.html
źródło