2010-10-15 6 views
1

Je développe un petit mécanisme de recherche simple et je veux permettre à l'utilisateur de rechercher des morceaux de texte avec des espaces. Par exemple, un utilisateur peut rechercher le nom d'une personne:C# Analyser le texte dans les citations

Nom: John Smith

Je puis "John Smith".Split(' ') dans un tableau de deux éléments, {"John","Smith"}. Je retourne ensuite tous les enregistrements qui correspondent "John" ET "Smith" en premier suivi par les enregistrements qui correspondent soit "John" OR "Smith." Je retourne ensuite aucun enregistrement pour aucune correspondance. Ce n'est pas un scénario compliqué et j'ai cette partie qui fonctionne.

Je voudrais maintenant être en mesure de permettre à l'utilisateur de retourner uniquement les enregistrements qui correspondent à « John Smith »

Je voudrais utiliser une syntaxe de devis de base pour la recherche. Donc, si un utilisateur veut rechercher "John Smith" OU Pocahontas, ils entreront: "John Smith" Pocahontas. L'ordre des termes est absolument hors de propos; "John Smith" n'a pas la priorité sur Pocahontas parce qu'il vient en premier dans la liste.

J'ai deux idées principales sur la façon dont je devrais analyser l'entrée. Je pense qu'un point d'action logique serait de trouver la substance entre guillemets; puis supprimez-le de la chaîne d'origine et insérez-le dans une liste distincte. Ensuite, tout ce qui reste de la chaîne d'origine pourrait être divisé sur l'espace et inséré dans cette liste séparée. S'il y a 1 citation ou un nombre impair, il est simplement retiré de la liste.

Comment puis-je trouver les correspondances de l'intérieur de regex? Je connais regex.Replace, mais comment je passerais à travers les matches et les insérer dans une liste. Je sais qu'il y a une bonne façon de le faire en utilisant le délégué de MatchEvaluator et linq, mais je ne sais rien sur regex dans C#.

+0

double possible de [expression régulière pour diviser sur des espaces moins entre guillemets] (http://stackoverflow.com/questions/554013/regular-expression-to-split-on-spaces-unless-in-quotes – Lucero

Répondre

0

Utilisez une expression régulière comme ceci:

string input = "\"John Smith\" Pocahontas"; 
Regex rx = new Regex(@"(?<="")[^""]+(?="")|[^\s""]\S*"); 
for (Match match = rx.Match(input); match.Success; match = match.NextMatch()) { 
    // use match.Value here, it contains the string to be searched 
} 
+0

@downvoter: Pourquoi le downvote? – Lucero

1

EDIT: est revenu à cet onglet withou rafraîchissante et n'a pas réalisé cette question a été déjà répondu ... réponse acceptée est mieux. Je pense que tirer d'abord les choses entre guillemets avec regex est une bonne idée. Peut-être quelque chose comme ceci:

String sampleInput = "\"John Smith\" Pocahontas Bambi \"Jane Doe\" Aladin"; 

//Create regex pattern 
Regex regex = new Regex("\"([^\".]+)\""); 

List<string> searches = new List<string>(); 

//Loop through all matches from regex 
foreach (Match match in regex.Matches(sampleInput)) 
{ 
    //add the match value for the 2nd group to the list 
    //(1st group is the entire match) 
    //(2nd group is the first parenthesis group in the defined regex pattern 
    // which in this case is the text inside the quotes) 
    searches.Add(match.Groups[1].Value); 
} 

//remove the matches from the input 
sampleInput = regex.Replace(sampleInput, String.Empty); 

//split the remaining input and add the result to our searches list 
searches.AddRange(sampleInput.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries)); 
0

J'avais besoin de la même fonctionnalité que Shawn mais je ne voulais pas utiliser regex. Voici une solution simple que j'ai trouvée utilise Split() au lieu de regex pour quiconque ayant besoin de cette fonctionnalité.

Cela fonctionne parce que la méthode Split, par défaut, créera des entrées vides dans le tableau pour les valeurs de recherche consécutives dans la chaîne source. Si nous divisons sur le caractère de citation alors le résultat est un tableau où les entrées indexées paires sont des mots individuels et les entrées indexées impaires seront les phrases de citations.

Exemple:

“John Smith” Pocahontas 

Résultats dans

item(0) = (empty string) 
item(1) = John Smith 
item(2) = Pocahontas 

Et

1 2 “3 4” 5 “6 7” “8 9” 

Résultats dans

item(0) = 1 2 
item(1) = 3 4 
item(2) = 5 
item(3) = 6 7 
item(4) = (empty string) 
item(5) = 8 9 

Notez qu'une citation non concordante donnera une phrase de la dernière citation à la fin de la chaîne d'entrée.

public static List<string> QueryToTerms(string query) 
    { 
     List<string> Result = new List<string>(); 

     // split on the quote token 
     string[] QuoteTerms = query.Split('"'); 
     // switch to denote if the current loop is processing words or a phrase 
     bool WordTerms = true; 

     foreach (string Item in QuoteTerms) 
     { 
      if (!string.IsNullOrWhiteSpace(Item)) 
       if (WordTerms) 
       { 
        // Item contains words. parse them and ignore empty entries. 
        string[] WTerms = Item.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); 
        foreach (string WTerm in WTerms) 
         Result.Add(WTerm); 
       } 
       else 
        // Item is a phrase. 
        Result.Add(Item); 

      // Alternate between words and phrases. 
      WordTerms = !WordTerms; 
     } 
     return Result; 
    } 
Questions connexes