IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Expression régulière "non greedy" en Java


Sujet :

Langage Java

  1. #1
    Nouveau membre du Club
    Inscrit en
    Février 2008
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 31
    Points : 28
    Points
    28
    Par défaut Expression régulière "non greedy" en Java
    Bonjour,

    J'aimerai pouvoir récupérer la petite chaine de caractère qui commence par 'd' fini par 'a' et contient 'o'

    Exemple : "fondjswxaeqobdnoajezbpfrehanxi" => "dnoa"

    Voilà mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Pattern pattern = Pattern.compile("d.*?o.*?a");
    Matcher matcher = pattern.matcher("fondjswxaeqobdnoajezbpfrehanxi");
    while (matcher.find()) {
      system.out.println(matcher.group());
    }
    Ce code affiche "djswxaeqobdnoa" et non "dnoa".

    Comment faire pour bien retourner la plus petite ?

    Merci

  2. #2
    Nouveau membre du Club
    Inscrit en
    Février 2008
    Messages
    31
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 31
    Points : 28
    Points
    28
    Par défaut
    La solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    String shortest = null;
    Pattern pattern = Pattern.compile("(?=(d.*?o.*?a))");
    Matcher matcher = pattern.matcher("ondjswxaeqobdnoajezbpfrehanxi");
    while (matcher.find()) {
    for (int i = 1; i <= matcher.groupCount(); i++) {
        if (shortest == null || matcher.group(i).length() < shortest.length()) {
            shortest = matcher.group(i);
        }
    }

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Joli trick avec le positive lookahead pour forcer find() à avancer caractère par caractère .

    Mais il est inutile de boucler sur les groupes : il n'y en a qu'un, et c'est le numéro 1. Il suffit de faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    String shortest = null;
    Pattern pattern = Pattern.compile("(?=(d.*?o.*?a))");
    Matcher matcher = pattern.matcher("ondjswxaeqobdnoajezbpfrehanxi");
    while (matcher.find()) {
      String candidate = matcher.group(1);
      if (shortest == null || candidate.length() < shortest.length()) {
        shortest = candidate;
      }
    }
    Comme je n'aime pas trop les tricks et je préfère garder un programme simple à lire et qui exprime clairement mon intention, voici comment j'aurais fait sans modifier la regex :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    String shortest = null;
    Pattern pattern = Pattern.compile("d.*?o.*?a");
    Matcher matcher = pattern.matcher("ondjswxaeqobdnoajezbpfrehanxi");
     
    int start = 0;
    while (matcher.find(start)) {
      String candidate = matcher.group();
      if (shortest == null || candidate.length() < shortest.length()) {
        shortest = candidate;
      }
      start = matcher.start()+1;
    }
    Pareil, find() n'avance que d'un caractère à la fois.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Ou plus simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Pattern pattern = Pattern.compile("d[^d]*?o.[^a]*?a");
    Matcher matcher = pattern.matcher("fondjswxaeqobdnoajezbpfrehanxi");
    while (matcher.find()) {
      system.out.println(matcher.group());
    }

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Hum. Je comprends pas trop l'intérêt du [^a], je suppose que c'est une erreur d'inattention.

    Mais sinon je vois l'idée : "invalider la recherche si on trouve un d entre le premier d et le o, pour s'assurer d'avoir le plus court."
    Ouais, ok, mais alors... Entre le o et le a, il faut rejeter toute séquence valide de d suivi de o... Ça peut se faire, avec un negative lookbehind. Mais "plus simplement" je suis pas convaincu.

    La regex donnée en exemple ne trouve pas le plus court. (précisément parce qu'on tombe sur une séquence de d suivi de o, qui elle-même est suivie d'une autre séquence de d suivi de o, avant de tomber sur le a.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Ha oui tiens, au temps pour moi

  7. #7
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 858
    Points : 6 556
    Points
    6 556
    Par défaut
    Une solution sans lookarounds:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    d[^do]*o[^da]*(?>d[^oa]*)*a
    Brachygobius xanthozonus
    Ctenobrycon Gymnocorymbus

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Euh, ouais, mais indépendant ou lookaround, la différence en termes de clarté...

    Enfin je dis ça, l'indépendant est là que pour des raisons de performances finalement. La même solution serait d[^do]*o[^da]*(d[^oa]*)*a... Qui marche !
    Mais à nouveau, en termes de clarté...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. expression régulière décimale non fonctionnelle
    Par drumtof dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 10/09/2009, 11h01
  2. Expression Régulière avec Quote
    Par jon301 dans le forum Langage
    Réponses: 3
    Dernier message: 25/10/2006, 22h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo