Comment créer un motif en utilisant une expression régulière dans Scala?

Je voudrais pouvoir trouver une correspondance entre la première lettre d’un mot et l’une des lettres d’un groupe tel que “ABC”. En pseudocode, cela pourrait ressembler à ceci:

case Process(word) => word.firstLetter match { case([ac][AC]) => case _ => } } 

Mais comment saisir la première lettre de Scala au lieu de Java? Comment exprimer correctement l’expression régulière? Est-il possible de le faire dans une classe de cas ?

Vous pouvez le faire car les expressions régulières définissent des extracteurs, mais vous devez d’abord définir le modèle de regex. Je n’ai pas access à une REPL Scala pour tester cela, mais quelque chose comme ça devrait fonctionner.

 val Pattern = "([a-cA-C])".r word.firstLetter match { case Pattern(c) => c bound to capture group here case _ => } 

Depuis la version 2.10, on peut utiliser la fonction d’interpolation de chaîne de Scala:

 implicit class Regex(sc: SsortingngContext) { def r = new util.matching.Regex(sc.parts.mkSsortingng, sc.parts.tail.map(_ => "x"): _*) } scala> "123" match { case r"\d+" => true case _ => false } res34: Boolean = true 

Encore mieux, on peut lier des groupes d’expression régulière:

 scala> "123" match { case r"(\d+)$d" => d.toInt case _ => 0 } res36: Int = 123 scala> "10+15" match { case r"(\d\d)${first}\+(\d\d)${second}" => first.toInt+second.toInt case _ => 0 } res38: Int = 25 

Il est également possible de définir des mécanismes de liaison plus détaillés:

 scala> object Doubler { def unapply(s: Ssortingng) = Some(s.toInt*2) } defined module Doubler scala> "10" match { case r"(\d\d)${Doubler(d)}" => d case _ => 0 } res40: Int = 20 scala> object isPositive { def unapply(s: Ssortingng) = s.toInt >= 0 } defined module isPositive scala> "10" match { case r"(\d\d)${d @ isPositive()}" => d.toInt case _ => 0 } res56: Int = 10 

Un exemple impressionnant de ce qui est possible avec Dynamic est présenté dans le billet de blog Introduction à Type Dynamic :

 object T { class RegexpExtractor(params: List[Ssortingng]) { def unapplySeq(str: Ssortingng) = params.headOption flatMap (_.r unapplySeq str) } class StartsWithExtractor(params: List[Ssortingng]) { def unapply(str: Ssortingng) = params.headOption filter (str startsWith _) map (_ => str) } class MapExtractor(keys: List[Ssortingng]) { def unapplySeq[T](map: Map[Ssortingng, T]) = Some(keys.map(map get _)) } import scala.language.dynamics class ExtractorParams(params: List[Ssortingng]) extends Dynamic { val Map = new MapExtractor(params) val StartsWith = new StartsWithExtractor(params) val Regexp = new RegexpExtractor(params) def selectDynamic(name: Ssortingng) = new ExtractorParams(params :+ name) } object p extends ExtractorParams(Nil) Map("firstName" -> "John", "lastName" -> "Doe") match { case p.firstName.lastName.Map( Some(p.Jo.StartsWith(fn)), Some(p.`.*(\\w)$`.Regexp(lastChar))) => println(s"Match! $fn ...$lastChar") case _ => println("nope") } } 

Comme le souligne Delnan, le mot-clé de match dans Scala n’a rien à voir avec les expressions rationnelles. Pour savoir si une chaîne correspond à une expression Ssortingng.matches , vous pouvez utiliser la méthode Ssortingng.matches . Pour savoir si une chaîne commence par a, b ou c en minuscule ou en majuscule, l’expression régulière devrait ressembler à ceci:

 word.matches("[a-cA-C].*") 

Vous pouvez lire cette expression régulière comme “l’un des caractères a, b, c, A, B ou C suivi de n’importe quoi” ( . Signifie “n’importe quel caractère” et * signifie “zéro ou plusieurs fois”, donc “. *” chaîne).

Pour développer un peu la réponse d’Andrew : Le fait que les expressions régulières définissent des extracteurs peut être utilisé pour décomposer les sous-chaînes correspondant très bien à l’expression rationnelle en utilisant la correspondance de Scala, par exemple:

 val Process = """([a-cA-C])([^\s]+)""".r // define first, rest is non-space for (p <- Process findAllIn "aha bah Cah dah") p match { case Process("b", _) => println("first: 'a', some rest") case Process(_, rest) => println("some first, rest: " + rest) // etc. } 

Notez que l’approche de la réponse de @AndrewMyers fait correspondre la chaîne entière à l’expression régulière, avec pour effet d’ancrer l’expression régulière aux deux extrémités de la chaîne en utilisant ^ et $ . Exemple:

 scala> val MY_RE = "(foo|bar).*".r MY_RE: scala.util.matching.Regex = (foo|bar).* scala> val result = "foo123" match { case MY_RE(m) => m; case _ => "No match" } result: Ssortingng = foo scala> val result = "baz123" match { case MY_RE(m) => m; case _ => "No match" } result: Ssortingng = No match scala> val result = "abcfoo123" match { case MY_RE(m) => m; case _ => "No match" } result: Ssortingng = No match 

Et avec no .* à la fin:

 scala> val MY_RE2 = "(foo|bar)".r MY_RE2: scala.util.matching.Regex = (foo|bar) scala> val result = "foo123" match { case MY_RE2(m) => m; case _ => "No match" } result: Ssortingng = No match 

Ssortingng.matches est la façon de faire la correspondance de motifs dans le sens regex.

Mais à côté de cela, word.firstLetter dans le vrai code Scala ressemble à:

 word(0) 

Scala traite les chaînes comme une suite de caractères, donc si pour une raison quelconque vous vouliez obtenir explicitement le premier caractère de la chaîne et y faire correspondre, vous pourriez utiliser quelque chose comme ceci:

 "Cat"(0).toSsortingng.matches("[a-cA-C]") res10: Boolean = true 

Je ne propose pas cela comme moyen général de faire des correspondances de regex, mais cela est conforme à l’approche que vous proposez pour trouver d’abord le premier caractère d’une chaîne et le faire correspondre à une regex.

EDIT: Pour être clair, comme je le ferais, comme d’autres l’ont dit:

 "Cat".matches("^[a-cA-C].*") res14: Boolean = true 

Je voulais juste montrer un exemple aussi proche que possible de votre pseudocode initial. À votre santé!

Nous devons d’abord savoir que l’expression régulière peut être utilisée séparément. Voici un exemple:

 import scala.util.matching.Regex val pattern = "Scala".r // <=> val pattern = new Regex("Scala") val str = "Scala is very cool" val result = pattern findFirstIn str result match { case Some(v) => println(v) case _ => } // output: Scala 

Deuxièmement, il convient de noter que combiner une expression régulière avec une correspondance de modèle serait très puissant. Voici un exemple simple.

 val date = """(\d\d\d\d)-(\d\d)-(\d\d)""".r "2014-11-20" match { case date(year, month, day) => "hello" } // output: hello 

En fait, l’expression régulière elle-même est déjà très puissante. la seule chose que nous devons faire est de le rendre plus puissant par Scala. Voici d’autres exemples dans le document Scala: http://www.scala-lang.org/files/archive/api/current/index.html#scala.util.matching.Regex