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 !
3 Réponses :
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.
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.
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"); } }
Cela vous donnera un pourcentage de correspondance "brut".
Voici comment cela fonctionne:
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.
Comptez le nombre de mots du terme de recherche qui apparaissent dans le texte.
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.
Comment faites-vous une boucle? Avez-vous chaque mot sous forme d'une seule
String
ou appelez-vouscontains (...)
avec uneString
constituée d'un ensemble de mots ( comme dans votre énumération)? Je pense que vous devez appeler la méthodecontains ()
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 .