2010-08-04 3 views
1

J'essaie de simplement se débarrasser de double mots consécutifs à partir d'un fichier texte, et quelqu'un a dit que je pouvais faire quelque chose comme ceci:Motif, matcher en Java, REGEX aide

Pattern p = Pattern.compile("(\\w+) \\1"); 
StringBuilder sb = new StringBuilder(1000); 
int i = 0; 
for (String s : lineOfWords) { // line of words is a List<String> that has each line read in from txt file 
Matcher m = p.matcher(s.toUpperCase()); 
// and then do something like 
while (m.find()) { 
    // do something here 
} 

J'ai essayé de regarder le m.end pour voir si je pourrais créer une nouvelle chaîne, ou enlever le (s) article (s) où les allumettes sont, mais je n'étais pas sûr comment cela fonctionne après avoir lu la documentation. Par exemple, en cas de test pour voir comment cela a fonctionné, je l'ai fait:

if (m.find()) { 
System.out.println(s.substring(i, m.end())); 
    } 

Pour le fichier texte qui a: This is an example example test test test.

Pourquoi ma sortie This is?

Edit:

si j'ai un lineOfWords de AraryList qui lit chaque ligne à partir d'une ligne de fichier txt, puis créer un nouveau ArrayList pour contenir la chaîne modifiée. Par exemple

List<String> newString = new ArrayList<String>(); 
for (String s : lineOfWords { 
    s = s.replaceAll(code from Kobi here); 
    newString.add(s); 
} 

mais alors il ne me donne pas les nouveaux, mais l'original s. Est-ce à cause de la copie peu profonde ou profonde?

+0

Qu'est-ce que 'i' dans ce second fragment? Il n'y a aucune trace nulle part ailleurs dans le code que vous montrez ... –

+0

Désolé, je suis égal à 0, je l'ai ajouté. – Crystal

+0

Salut, Crystal. Il est préférable de poser une nouvelle question dans ce cas, c'est vraiment une autre question sur un autre sujet. (sur une note pertinente - quand j'ai étudié Java, il n'y avait pas de génériques ni de boucles foreach ': P') – Kobi

Répondre

3

Essayez quelque chose comme:

s = s.replaceAll("\\b(\\w+)\\b(\\s+\\1)+\\b", "$1"); 

Ce regex est un peu plus fort que le vôtre - il vérifie les mots entiers (sans résultat partiel), et se débarrasse de tout nombre de répétitions consécutives.
La regex capture un premier mot: \b(\w+)\b, puis tente de faire correspondre les espaces et les répétitions de ce mot: (\s+\1)+. Le \b final est d'éviter la correspondance partielle de \1, comme dans "for formatting".

+0

Cela a beaucoup aidé. Y at-il un moyen de vérifier les choses qui sont différentes cas? Comme "test de test"? – Crystal

+0

@Crystal - Merci! Vous pouvez ajouter '(? I)' au début de la regex pour le rendre insensible à la casse, cela semble être la solution standard pour 'replaceAll'. – Kobi

+0

Une autre question Kobi si vous avez une seconde, si je suis en boucle à travers un Arraylist qui a mes lignes de mots d'un fichier de test, et si j'ai fait une boucle foreach pour le parcourir, comme pour (String s: lineOfWords) {s = s.replaceAll ..., alors comment j'ajouterais ce nouveau "s" à ma nouvelle ArrayList pour revenir. Je pense que cela a à voir avec la copie peu profonde ou profonde, mais pas sûr. J'ai essayé le pseudo-codage dans ma question initiale ci-dessus. THX! – Crystal

1

Le premier résultat est "Th EST IS un exemple ...", donc m.end() points à la fin de la seconde "est". Je ne suis pas sûr pourquoi vous utilisez i pour l'index de départ; essayez plutôt m.start().

Pour améliorer votre expression régulière, utilisez \b avant et après le mot pour indiquer qu'il doit y avoir des limites de mots: (\\b\\w+\\b). Sinon, comme vous le voyez, vous obtiendrez des correspondances à l'intérieur des mots.