2010-09-30 7 views
1

J'écris un programme en C# qui compare les chaînes de caractères de la même manière que Google recherche des documents pour les mots-clés.Comment puis-je voir si une chaîne en contient un autre de manière lâche (casse, espace supplémentaire et ponctuation ignorés)?

Je veux une recherche de "débordement de pile" pour retourner vrai pour "débordement de pile" (clair), "C'est le débordement de pile." (au milieu), "Bienvenue dans Stack Overflow". (cas insensible), "J'aime le débordement de la pile." (espace variable), et "Qui met un tiret dans le débordement de la pile?", mais pas "" stackoverflow "(pas d'espace). Je pensais que je pourrais utiliser une expression régulière comme "stack ([-] |.) + Overflow", il semble exagéré de devoir remplacer chaque espace de chaque mot-clé par un jeu de caractères pour chaque nouveau mot-clé. Parce que "stack overflow" n'est pas la seule chaîne que je recherche, je dois le faire de manière pragmatique.

+0

Il semble que vous ayez besoin d'algorithmes de logique floue. Une recherche rapide fait apparaître la distance de Levenshtein comme un moyen de mesurer le nombre de modifications nécessaires pour transformer une chaîne en une autre. –

+0

Cette question connexe offre quelques possibilités: http://stackoverflow.com/questions/1358687/what-are-good-methods-to-find-the-relatedness-of-two-bodies-of-text –

Répondre

1

Pour répondre à vos spécifications, vous pouvez d'abord faire

newSearchString = Regex.Replace(Regex.Escape(searchString), @"\s+", @"[\s\p{P}]+"); 

(pour transformer votre chaîne de recherche de texte brut dans une expression régulière qui permet aussi la ponctuation dans des endroits où il y avait seulement des espaces), puis appliquer cette regex à tout ce que vous cherchez. Mais bien sûr, cela ne correspondra pas à la moindre faute de frappe, tandis qu'un algorithme utilisant la distance de Levensthein correspondra également à "Stak Overfloor".

1

Si vous voulez simplement obtenir l'effet dans le cas spécifique que vous avez mentionné, vous pouvez utiliser des expressions régulières pour remplacer les jetons que vous voulez ignorer par un seul espace (ou chaîne vide).

Si vous voulez une solution plus élaborée, vous pouvez utiliser la programmation dynamique pour obtenir la plus petite permutation nécessaire pour transformer la première chaîne en seconde. Cela permettra également de faire correspondre avec (quelques) lettres manquantes ou fautes de frappe.

+0

Je suis Je cherche plus que le cas spécifique du "stack overflow" car j'aurai des centaines de mots-clés à comparer. Pour le moment, je vais remplacer tous les espaces par la classe de caractères regex, mais j'espère que quelque chose d'autre va se présenter. –

+0

Je voulais dire le cas spécifique «ignorez cas, espace et ponction». Si vous voulez gérer les correspondances possibles dans le cas de fautes de frappe, alors vous cherchez quelque chose de plus évolué, comme la programmation dynamique. Si vous comparez la chaîne d'entrée avec toutes les correspondances possibles, elle renvoie un coût de correspondance pour chaque chaîne et vous pouvez sélectionner le mot clé ayant le coût le plus bas comme une "correspondance" avec un certain degré d'incertitude (coût de correspondance élevé - correspondance improbable) . Rien ne vous empêche d'utiliser une approche hybride: remplacez la casse, l'espace, la ponctuation, puis utilisez la programmation dynamique. –

0

Si vous comparez contre court cordes, puis la meilleure façon que je peux voir serait de dépouiller tout l'espace blanc et d'autres personnages des deux chaînes et de faire une string.Contains simple.

Questions connexes