Supongamos que tengo un patrón Regex con el que quiero hacer coincidir muchas cadenas.
val Digit = """\d""".r
Solo quiero verificar si una cadena determinada coincide completamente con la expresión regular. ¿Cuál es una forma buena e idiomática de hacer esto en Scala?
Sé que puedo hacer coincidir patrones en Regexes, pero esto no es sintácticamente muy agradable en este caso, porque no tengo grupos para extraer:
scala> "5" match { case Digit() => true case _ => false }
res4: Boolean = true
O podría volver al patrón de Java subyacente:
scala> Digit.pattern.matcher("5").matches
res6: Boolean = true
que tampoco es elegante.
¿Existe una solución mejor?
"5" match { case Digit() => true case _ => false }
ve mejor que usar un objeto de patrón subyacente.Respuestas:
Para responder a mi propia pregunta, usaré el patrón "proxeneta mi biblioteca"
object RegexUtils { implicit class RichRegex(val underlying: Regex) extends AnyVal { def matches(s: String) = underlying.pattern.matcher(s).matches } }
y úsalo así
import RegexUtils._ val Digit = """\d""".r if (Digit matches "5") println("match") else println("no match")
a menos que a alguien se le ocurra una solución mejor (estándar).
Notas
No me propongo
String
limitar el alcance de los posibles efectos secundarios.unapplySeq
no lee muy bien en ese contexto.fuente
String
lugar de eso, hice proxenetismo y esto funciona bien hasta ahora, a pesar deString
la función de miembromatches(regex: String)
.misses
. Match y missmatch :-) Es tan molesto tener que escribir en!s.matches(r)
lugar des misses r
. Hmm"5" matches "\\d"
que sugirió @polygenelubricants?case r(_*) =>
.No conozco muy bien a Scala, pero parece que puedes hacer:
"5".matches("\\d")
Referencias
fuente
.pattern.matcher(text).matches
es el camino a seguir. Puede ocultar la verbosidad bajo algún método de utilidad u operador sobrecargado o algo si Scala lo admite.Para la coincidencia completa, puede usar unapplySeq . Este método intenta hacer coincidir el objetivo (coincidencia completa) y devuelve las coincidencias.
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
fuente
case
s de unmatch
bloque."""\d""".r.unapplySeq("5").isDefined //> res1: Boolean = true """\d""".r.unapplySeq("a").isDefined //> res2: Boolean = false
fuente
La respuesta está en la expresión regular:
val Digit = """^\d$""".r
Luego use uno de los métodos existentes.
fuente
String/Pattern/Matcher.matches
, en Java al menos, la cadena completa ya coincide. Creo que el problema es solo el estilo / idioma para expresiones regulares en Scala, es decir, cuáles son esos "uno de los métodos existentes".Matcher.matches
es una aberración. Ok, hace posibles algunas optimizaciones, aunque no sé si la biblioteca de Java realmente lo aprovecha. Pero la forma estándar para que las expresiones regulares expresen que se requiere una coincidencia completa es usar anclas. Dado que la biblioteca de Scala no proporciona un método de coincidencia completo, la forma correcta de hacerlo es usar anclajes. O eso, o usa la biblioteca de Java.matches
, pero está bien. En cuanto aOption
vsBoolean
, agreguenonEmpty
al final y obtendrá elBoolean
.Usando la biblioteca estándar de Scala y un patrón de expresiones regulares precompilado y coincidencia de patrones (que es el estado de la técnica de Scala):
val digit = """(\d)""".r "2" match { case digit( a) => println(a + " is Digit") case _ => println("it is something else") }
más para leer: http://www.scala-lang.org/api/2.12.1/scala/util/matching/index.html
fuente