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

Collection et Stream Java Discussion :

[regex]Remplacer un mot exact


Sujet :

Collection et Stream Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Par défaut [regex]Remplacer un mot exact
    Bonjour tout le monde.

    Je cherche à remplacer un mot exact dans une chaine de caractère, mais j'ai un peu de mal.

    En fait j'ai la chaine suivante "param23 + 12 + param2" (sans les guillemets) et j'ai également une Map avec la valeur de mes param. Map<String, Double> = [param2 15],[param23 9].
    Je voudrais donc remplacer mes paramxx par leur valeurs respective.
    Je n'arrive pas à trouver la regex qui me remplace (dans un replaceAll - Java 1.4 oblige) param2 et seulement param2.
    En gros aujourd'hui mon code me renvoie ça : 153 + 12 + 15 car il remplace param2 dans param23... ce qui n'est pas correct.

    Voici le susdit code si ça peut aider.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
        /**
         * Replaces the keys of the formula with their values in the map.
         * 
         * @param originalFormula
         *           the original formula as it is extracted from the database. The
         *           values to be replaced needs to be both prefixed and postfixed by
         *           a space. <i>e.g.<b> key1 key2 </b>instead of<b> key1key2
         * @param replacementMap
         *           a map which takes any Strings as keys and any Strings as values.
         *           <i>e.g. The operator ID as keys and the parameter names or the
         *           parameter IDs as values .</I>
         * 
         * @return the formula updated with the replacementMap values instead of its
         *         keys.
         */
        public static String updateFormula(String originalFormula, Map replacementMap)
        {
            String newFormula = originalFormula;
     
            List keys = new ArrayList();
            keys.addAll(replacementMap.keySet());
     
            for (int i = 0; i < keys.size(); i++)
            {
                if (keys.get(i) != null)
                {
                    newFormula = newFormula.replaceAll(keys.get(i).toString(), replacementMap.get(keys.get(i)).toString());
                }
            }
     
            consoleLogger.debug("updateFormula(" + originalFormula + ") -> " + newFormula);
     
            return newFormula;
        }

  2. #2
    Membre éclairé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Par défaut
    J'ai également essayé ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
        public static String updateFormula(String originalFormula, Map replacementMap)
        {
            String newFormula = originalFormula;
     
            Pattern p = null;
            Matcher m = null;
     
            List keys = new ArrayList();
            keys.addAll(replacementMap.keySet());
     
            for (int i = 0; i < keys.size(); i++)
            {
                if (keys.get(i) != null)
                {
    //                newFormula = newFormula.replaceAll(keys.get(i).toString(), replacementMap.get(keys.get(i)).toString());
                    p = Pattern.compile(keys.get(i).toString());
                    m = p.matcher(newFormula);
     
                    newFormula = m.replaceAll(replacementMap.get(keys.get(i)).toString());
                }
            }
     
            Pims.consoleLogger.debug("updateFormula(" + originalFormula + ") -> " + newFormula);
     
            return newFormula;
        }
    Mais rien ni fait.

    De plus et ça aussi je ne comprend pas, Eclipse me jette à la compilation quand j'essaie par exemple de mettre un "\s" à la fin de ma regex keys.get(i).toString en me disant que ce n'est pas un caractère d'échappement valide. Pourtant la classe Pattern est formelle de ce côté là et me le donne bien comme échappement correct.

  3. #3
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Citation Envoyé par leminipouce
    Eclipse me jette à la compilation quand j'essaie par exemple de mettre un "\s" à la fin de ma regex keys.get(i).toString en me disant que ce n'est pas un caractère d'échappement valide.
    Pris en flag' de non-lecture de la FAQ : Pourquoi dois-je doubler/quadrupler le caractère anti-slash ('\') ?



    Sinon une petite remarque avant de commencer : tu crées une ArrayList temporaire pour rien : autant parcourir directement le keySet() !
    D'ailleurs pourquoi ne pas carrément parcourir l'entrySet() qui comporte le couple clef/valeur !



    Quand à ton problème plus précisément, voici un code qui devrait marcher :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	public static String updateFormula(String originalFormula, Map replacementMap) {
    		String newFormula = originalFormula;
     
    		Iterator keyIterator = replacementMap.entrySet().iterator();
    		while (keyIterator.hasNext()) {
    			Map.Entry entry = (Map.Entry) keyIterator.next();
    			String key = "(?<=\\p{Punct}|\\p{Space}|^)" + Pattern.quote( entry.getKey().toString() ) + "(?=\\p{Punct}|\\p{Space}|$)";
    			String value = entry.getValue().toString();
    			newFormula = newFormula.replaceAll( key, value);
    		}
    		//consoleLogger.debug("updateFormula(" + originalFormula + ") -> " + newFormula);
     
    		return newFormula;
    	}
    Pattern.quote() n'est disponible qu'à partir de Java 5.0, mais tu pourras trouver son équivalent 1.4 ici : Comment empêcher les expressions régulières d'interpréter une sous-chaînes ?
    Cela te permettra d'éviter que d'éventuelle caractères spéciaux dans tes clefs ne viennent "casser" ta regexp...


    Quand aux éléments qui entoure la clef, ils permettent de rajouter des contraintes sur les éléments qui entoure la chaine (sans les prendre en compte dans le remplacement) :

    • "(?<=\\p{Punct}|\\p{Space}|^)" :
      "(?<=)" permet de spécifier les éléments qui précèdent le terme. Ici on n'autorise que \\p{Punct}|\\p{Space}|^, soit respectivement : un caractères de ponctuations, un caractères d'espacement, ou le début de la chaine.

    • "(?=\\p{Punct}|\\p{Space}|$)" Fais la même chose, mais pour les caractères suivant :
      "(?=)" permet de spécifier les éléments qui suivent le terme. Ici on n'autorise que \\p{Punct}|\\p{Space}|$, soit respectivement : un caractères de ponctuations, un caractères d'espacement, ou la fin de la chaine.


    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	String s = "param2 + param23 + 12 + 8param2 + 0 + param2";
     
    	Map m = new HashMap();
    	m.put("param2", "5555");
     
    	System.out.println(s);
    	System.out.println(updateFormula(s, m));
    Donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    param2 + param23 + 12 + 8param2 + 0 + param2
    5555 + param23 + 12 + 8param2 + 0 + 5555
    a++

  4. #4
    Membre éclairé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Par défaut Merci !
    Est-il vraiment nécessaire de dire que ça marche ?

    Par contre j'avais bien lu ce passage là de la FAQ, mais je dois reconnaître que sur le coup je ne l'avais pas compris comme ça. Pourtant il est limpide ! Et je ne l'ai pas relu depuis que je galère sur cette regexp.

    Bref ça marche nickel. Merci bien !

    [edit] Pour ce qui est des iterators j'avoue ne pas être trop familier avec eux... d'où l'ArrayList
    Par contre question performances garder une instance de Map.Entry dans la boucle n'est-il pas plus gourmand en ressources que déclarer la variable entry avant la boucle et ce contenter de changer sa valeur dans le while ?

  5. #5
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par leminipouce
    Par contre question performances garder une instance de Map.Entry dans la boucle n'est-il pas plus gourmand en ressources que déclarer la variable entry avant la boucle et ce contenter de changer sa valeur dans le while ?
    Non : je pense que le compilateur et/ou la JVM sait très bien gérer cela, et lorsque tu définis une référence dans une boucle elle ne sera alloué qu'une fois (comme si tu l'avais déclaré en dehors de la boucle).

    Par contre c'est plus propre car cela réduit bien le scope de visibilité de la variable

    a++

  6. #6
    Membre éclairé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Par défaut Super !
    Merci pour l'info J'étais persuadé du contraire...

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 23/12/2013, 16h40
  2. [Regex]Recherche de mots dans une chaîne
    Par lionel69 dans le forum Collection et Stream
    Réponses: 7
    Dernier message: 17/11/2005, 18h20
  3. Phrase et mot exacte
    Par Tigris94 dans le forum Requêtes
    Réponses: 2
    Dernier message: 16/07/2004, 10h24

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