3
votes

Java Searching String Contents pour une correspondance partielle

Je travaille sur un projet dans lequel j'ai besoin de rechercher dans un paragraphe de texte une chaîne particulière. Cependant, je n'ai pas besoin d'une correspondance exacte, mais plutôt d'une correspondance en%.

Par exemple, voici le paragraphe de texte que je recherche:

1) False
2) True
3) True
4) True
5) True
6) True
7) True
8) True
9) True
10) False

Et puis je cherche si des mots dans les lignes suivantes correspondent au paragraphe :

boolean found = med[x].toLowerCase().contains(condition[y].toLowerCase());

Mon approche initiale était d'utiliser un booléen et contient:

1)Unspecified acute lower respiratory infection
2)Vasomotor rhinitis
3)Allergic rhinitis due to pollen
4)Other seasonal allergic rhinitis
5)Allergic rhinitis due to food
6)Allergic rhinitis due to animal (cat) (dog) hair and dander
7)Other allergic rhinitis
8)"Allergic rhinitis, unspecified"
9)Chronic rhinitis
10)Chronic nasopharyngitis

cependant, les résultats sont négatifs pour chaque boucle à travers.

Les résultats que j'attends seraient:

Fluticasone Propionate Nasal Spray, USP 50 mcg per spray is a 
corticosteroid indicated for the management of the nasal symptoms of 
perennial nonallergic rhinitis in adult and pediatric patients aged 4 years 
and older."

Très nouveau pour Java et ses méthodes. Fondamentalement, si un mot de A correspond à un mot de B, marquez-le comme vrai. Comment je fais ça?

Merci !


2 commentaires

Comment faites-vous une boucle? Avez-vous chaque mot sous forme d'une seule String ou appelez-vous contains (...) avec une String constituée d'un ensemble de mots ( comme dans votre énumération)? Je pense que vous devez appeler la méthode contains () pour chaque mot pour obtenir des correspondances.


Il existe des outils avancés pour cela. N'essayez pas de le faire vous-même, à moins que vous ne suiviez ce projet dans le cadre d'une formation personnelle. Par exemple, jetez un œil à Aho-Corasick , ou peut-être à Elasticsearch .


3 Réponses :


2
votes

Vous devez d'abord tokeniser l'une des chaînes. Ce que vous faites maintenant, c'est essayer de faire correspondre toute la ligne.

Quelque chose comme celui-ci devrait fonctionner:

private Stream<String> tokenize(String s) {
   return Arrays.stream(s.split(" "))
                .map(String::toLowerCase)
                .map(s -> s.replaceAll("\\W", "")
                .filter(s -> !s.isEmpty());                   
}

Set<String> words =  tokenize(med[x]).collect(Collectors.toSet());

boolean found = tokenize(condition[y]).anyMatch(words::contains);

J'ai ajouté la suppression des caractères de ponctuation et des chaînes vides, afin que nous n'ayons pas de fausses correspondances sur ceux-ci . (Le \\ W supprime en fait les caractères qui ne sont pas dans [A-Za-z_0-9] , mais vous pouvez le changer en ce que vous voulez.) P >

Si vous en avez besoin pour être efficace, parce que vous avez beaucoup de texte, vous voudrez peut-être le retourner et utiliser un Set qui permet une recherche plus rapide.

String text = med[x].toLowerCase();
boolean found = 
  Arrays.stream(condition[y].split(" "))      
      .map(String::toLowerCase)
      .map(s -> s.replaceAll("\\W", "")
      .filter(s -> !s.isEmpty())
      .anyMatch(text::contains);

Vous pouvez également filtrer les mots stop , comme à , et etc. Vous pouvez utiliser la liste ici et ajouter un filtre supplémentaire après celui qui vérifie les chaînes vides, pour vérifier que la chaîne n'est pas un mot vide.


2 commentaires

J'ai essayé le premier bloc de code (j'ai dû tout ajouter sur une seule ligne, encore une fois débutant) mais il a tout renvoyé comme vrai. J'aurai BEAUCOUP de texte, je vais essayer de le transformer en un ensemble lorsque je pourrai trouver quelques minutes.


Essayez de déboguer un peu pour voir où il correspond au texte. Peut-être ses mots vides, ou peut-être quelque chose d'autre est pris en dehors de la ponctuation que nous supprimons. Vous pouvez ajouter quelque chose comme peek (System :: out) juste après le filter () pour voir quels mots sont extraits.



0
votes

Si vous construisez une liste avec les mots interrogeables, ce serait beaucoup plus facile. Supposons que votre paragraphe soit stocké sous forme de chaîne:

ArrayList<String> dictionary = new ArrayList<>();
dictionary.add("acute lower respiratory infection");
dictionary.add("rhinitis");
for(int i =0; i<dictionary.size(); i++){
    if(paragraph.contains(dictionary.get(i))){
        System.out.println(i + "True");
    }
    else{
         System.out.println(i +"False");
    }
}


0 commentaires

0
votes

Cela vous donnera un pourcentage de correspondance "brut".

Voici comment cela fonctionne:

  1. Divisez le texte à rechercher et le terme de recherche en un ensemble de mots. Cela se fait par fractionnement à l'aide d'une expression régulière. Chaque mot est converti en majuscules et ajouté à un ensemble.

  2. Comptez le nombre de mots du terme de recherche qui apparaissent dans le texte.

  3. Calculez le pourcentage de mots du terme de recherche qui apparaissent dans le texte.

Vous voudrez peut-être améliorer cela en supprimant les mots courants tels que "a", "le", etc.

    boolean matches = findMatch(searchText, searchTerm) > 0.0;

Résultat:

XXX

Si vous ne voulez pas de pourcentage, mais vrai ou faux, vous pouvez simplement faire ...,

    0.0% - Unspecified acute lower respiratory infection
    50.0% - Vasomotor rhinitis
    20.0% - Allergic rhinitis due to pollen
    25.0% - Other seasonal allergic rhinitis
    20.0% - Allergic rhinitis due to food
    20.0% - Allergic rhinitis due to animal (cat) (dog) hair and dander
    33.33333333333333% - Other allergic rhinitis
    33.33333333333333% - Allergic rhinitis, unspecified
    50.0% - Chronic rhinitis
    0.0% - Chronic nasopharyngitis

J'espère que cela vous aidera.


0 commentaires