StringTokenizer des problem!!! [Résolu]

Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
- - Dernière réponse : cheriner
Messages postés
6
Date d'inscription
vendredi 29 avril 2011
Dernière intervention
30 mai 2011
- 26 mai 2011 à 22:03
int count =0;
while(textReq.hasMoreTokens()){
String n= textReq.nextToken();

while(text.hasMoreTokens()){

if (n.equals(text.nextToken())){
count=count+1;
}}
//resultat
le nombre de similarité est :0
par contre g mis des similarité dans la requête
je sais pas c koi le problem !!!
aide
Afficher la suite 

Votre réponse

13 réponses

Meilleure réponse
Messages postés
15838
Date d'inscription
jeudi 8 août 2002
Dernière intervention
4 mars 2013
110
3
Merci
Salut,

Ton algorithme est un peu bancal : non seulement il ne produit pas se que tu veux, mais en plus, il est loin d'être optimisé !

Tout d'abord, pour qu'il fonctionne, il faut que tu réinitialise ton StringTokenizer dans ta première boucle, car une fois qu'il a parcourut tout ton fichier, et donc, que le text.hasMoreToken te renvoie false, il ne passera plus jamais dans la boucle... et du coup, il ne teste que le premier mot du textReq.

Ensuite, niveau optimisation, je te donne un cheminement à suivre pour bien que tu comprennes :
1/ Plutôt que de parcourir d'abord les mots entrées par l'utilisateur, puis les mots du fichier, fais l'inverse. Ca peut paraître tout bête, mais faire un tokenizer sur une dizaine de mots entrés par l'utilisateur, ca prends beaucoup moins de temps que de faire un tokenizer sur un milion de mots d'un fichier... Et donc, si l'utilisateur rentre 10 mots, au lieu de faire 10 * 1 000 000 tests longs, tu fais 1 000 000 * 10 tests courts. Niveau complexité, c'est pareil, mais niveau temps d'exécution, tu y gagne énormément !
Du coup, au lieu de :
int count =0;
while(textReq.hasMoreTokens()){
String n= textReq.nextToken();
// reinit du tokenizer de text
while(text.hasMoreTokens()){

if (n.equals(text.nextToken())){
count++;
}} 


Il vaut mieux faire :
int count =0;

while(text.hasMoreTokens()){

if (n.equals(text.nextToken())){
//réinit du tokenizer textreq

while(textReq.hasMoreTokens()){
String n= textReq.nextToken();

count++;
}} 

2/ Vu que ce sont des mots entrés par l'utilisateur, il n'y en aura pas des milions... alors pourquoi à chaque tour de boucle vouloir récupérer les mots entrés par l'utilisateur ? Stocke les dans un tableau, ce sera bien plus optimal (plus besoin de faire un tokenizer à chaque tour de boucle !) :
String[] mots = textReq.split(" ");
int count =0;
int taille = mots.length;

while(text.hasMoreTokens()){
for (int i = 0; i < taille; i++){
if (mots[i].equals(text.nextToken())){
count++;
}
} 


La complexité est la même, mais tu enlève le temps de traîtement du tokenizer sur la chaîne textreq.

3/ Pourquoi utiliser un tokenizer sur le fichier ? Tu perds énormément de temps à parcourir le fichier mot à mot !!! Là du coup, pour diminuer drastiquement la complexité, y'a une astuce toute simple : ne chercher QUE les occurences des mots à trouver, au lieu de parcourir 1 millions de mots un à un et tester à chaque fois, tu ne fait que chercher une centaine de mots (s'il y a une centaine d'occurence dans le fichier), et puis c'est tout !
Ce qui donne un truc du genre (fait de tête, à corriger très certainement) :
String[] mots = textReq.split(" ");
int count =0;
int taille = mots.length;
int index = 0;

for (int i = 0; i < taille; i++){
index = text.indexOf(mots[1]);
while(index > 0){
count++;
index=text.indexOf(mots[1]);
}
} 


Après tu aurais une autre optimisation possible : ne pas travailler avec des String mais avec un tableau de Byte, car c'est plus rapide de comparer des Byte que de comparer des String, mais là c'est du chipotage.
Bref, avec tout cà, tu vas passer d'un temps de traîtement de 10 * 1000000 du temps d'exécution du tokenizer à un temps de traîtement d'environ 10 * 100 du temps d'exécution du indexOf ! Ce qui veux dire que là où ton algorithme pouvait mettre 1 heure, la version optimisée ne prendrais plus que 1 minute...
______________________________________
DarK Sidious

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 121 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_DARKSIDIOUS
Messages postés
15838
Date d'inscription
jeudi 8 août 2002
Dernière intervention
4 mars 2013
110
3
Merci
Salut,

Oui normal, c'est une boucle infinie, il faut modifier le indexOf pour qu'il commence à la valeur de index + 1 et non à 0 à chaque fois !

Sinon, voici une version vraiment optimisée de ton code et fonctionnelle, profites-en, ca me ressemble pas de donner un code tout cuit :

Il utilise des expressions régulières pour faire le replace, et tenir compte qu'il doit s'agit d'un mot, et pas juste une chaîne au milieu d'une autre.
public static void main(String[] args){ 
  System.out.println("bonjour"); 
  readFile b =new readFile();
  String X=b.readFile();
  String replaceChaine = "(un )|(est )|( et)|(une )|(la )|(les )|(le )|(l')|(de )|(des )|(d' )|(pour )|(comme )|(ou )|(dans )";
         
  String S = X.toLowerCase().replaceAll(replaceChaine,"");

  System.out.println(S);
  System.out.println("entrer votre requete :");
  String req=lire.S();

  String reqElag=req.toLowerCase().replaceAll(replaceChaine,"");
  System.out.println(reqElag);
  String[] mots = reqElag.split(" ");
  int count =0;
  int taille = mots.length;
  int index = 0;

  for (int i = 0; i < taille; i++){
    index = S.indexOf(mots[i]);
    while(index > 0){
      count++;
      index=S.indexOf(mots[i], index + 1);
    }
  } 
  System.out.println ("le nombre de similariter est :"+count);	
}


Non seulement ce code est plus lisible, plus compréhensible, et plus facilement maintenable, mais il est aussi bien plus rapide.
______________________________________
DarK Sidious

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 121 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_DARKSIDIOUS
Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
0
Merci
textReq c est une requete entrer au clavier par l'utilisateur
text c est un fichier .txt lit par par la methode readFile que g implementer c tous pour le moment
Commenter la réponse de youorme
Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
0
Merci
package Indexation;

import java.util.StringTokenizer;

public class test {
public static void main(String[] args){ 
System.out.println("bonjour"); 
readFile b =new readFile();
String X=b.readFile();
StringTokenizer text= new StringTokenizer(X);
String S="";
System.out.println("Nombre de mots :"+ text.countTokens());
while(text.hasMoreTokens()){
 String W= text.nextToken();
if(!((W.equals("un"))||(W.equals("est"))||(W.equals("et"))||(W.equals("une"))||(W.equals("la"))||(W.equals("les"))
||(W.equals("le"))||(W.equals("l'"))||(W.equals("de"))||(W.equals("des"))||(W.equals("d'"))||(W.equals("pour"))
||(W.equals("comme"))||(W.equals("ou"))||(W.equals("dans")))){

S= S +" "+ W;
}
}
System.out.println(S);
System.out.println("entrer votre requete :");
String req=lire.S();
StringTokenizer textReq= new StringTokenizer(req);
String reqElag="";
System.out.println("Nombre de mots :"+ textReq.countTokens());
while(textReq.hasMoreTokens()){
String w= textReq.nextToken();
if(!((w.equals("un"))||(w.equals("est"))||(w.equals("et"))||(w.equals("une"))||(w.equals("la"))||(w.equals("les"))
||(w.equals("le"))||(w.equals("l'"))||(w.equals("de"))||(w.equals("des"))||(w.equals("d'"))||(w.equals("pour"))
||(w.equals("comme"))||(w.equals("ou"))||(w.equals("dans")))){

reqElag+=" "+ w;

}
}System.out.println(reqElag);
String[] mots = reqElag.split(" ");
int count =0;
int taille = mots.length;
int index = 0;

for (int i = 0; i < taille; i++){
index = S.indexOf(mots[1]);
while(index > 0){
count++;
index=S.indexOf(mots[1]);
}
} System.out.println ("le nombre de similariter est :"+count);	

}


}

// laffichge ne marche po
et g pa compris pk t'as mis mots[1] et non pas mot[i]
merci
Commenter la réponse de youorme
Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
0
Merci
en faite il deux autre classe readFile pour lire un fichier text
lire pour la lecture clavier
Commenter la réponse de youorme
Messages postés
15838
Date d'inscription
jeudi 8 août 2002
Dernière intervention
4 mars 2013
110
0
Merci
Salut,

Oui c'est une erreur de ma part, il faut bien mettre mots[i] au lieu de mots[1]
______________________________________
DarK Sidious
Commenter la réponse de cs_DARKSIDIOUS
Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
0
Merci
alors pk l'affichage ne marche po stp??
Commenter la réponse de youorme
Messages postés
15838
Date d'inscription
jeudi 8 août 2002
Dernière intervention
4 mars 2013
110
0
Merci
Salut,

Tu aimes faire les trucs non optimisés apparement :)

Pour remplacer les mots que tu ne veux pas tester, il te suffit de faire des replaces, plutôt que de passer par un StringTokenizer (encore !) :

Au lieu de :
while(text.hasMoreTokens()){
 String W= text.nextToken();
if(!((W.equals("un"))||(W.equals("est"))||(W.equals("et"))||(W.equals("une"))||(W.equals("la"))||(W.equals("les"))
||(W.equals("le"))||(W.equals("l'"))||(W.equals("de"))||(W.equals("des"))||(W.equals("d'"))||(W.equals("pour"))
||(W.equals("comme"))||(W.equals("ou"))||(W.equals("dans")))){

S= S +" "+ W;
}
}


mets plutôt :
String S = X.replaceAll("un", "");
String S = S.replaceAll("est", "");
String S = S.replaceAll("et", ""); 
// etc.


idem pour le texte de l'utilisateur

Après, qu'est-ce que tu veux dire par "l'affichage ne marche pas" ? Ca t'affiche quoi ? 0 ?


Sinon, evite le langage SMS, tu as un clavier complet, alors profites-en pour écrire normalement, c'est chiant à lire !
______________________________________
DarK Sidious
Commenter la réponse de cs_DARKSIDIOUS
Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
0
Merci
ok dsl
l'affichage ne marche c est a dire le System.out.println ("le nombre de similariter est :"+count);
n'affiche rien :)
et pour les chose non optimiser je suit encore débutant je cherche un prog qui marche pour le moment même mes professeur ne vont pas tenir compte de l'optimisation
mais ca n'empêche pas de te dire merci pour tes consigne
Commenter la réponse de youorme
Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
0
Merci
en plus si j'utilise la fonction .replaceAll
elle va remplacer meme le sous cahine indiquer dans une chaine donner comme par exemple si je veux eliminer le mot "le"
il va l'eliminer de la chane "exemple" ce qui devient "exemp" ;)
et je ve pa que ca se produit
Commenter la réponse de youorme
Messages postés
18
Date d'inscription
dimanche 25 novembre 2007
Dernière intervention
18 avril 2010
0
Merci
ok merci bien de votre aide ;)
mais dans replacechaine() il faut ke avant et apres le mots mettre un espace
:)
Commenter la réponse de youorme
Messages postés
6
Date d'inscription
vendredi 29 avril 2011
Dernière intervention
30 mai 2011
0
Merci
[^^happy13]
Commenter la réponse de cheriner
Messages postés
6
Date d'inscription
vendredi 29 avril 2011
Dernière intervention
30 mai 2011
0
Merci
je suis recherch a un algorithme pour calcule la similarite entre deux schema xml
Commenter la réponse de cheriner

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.