2010-10-27 9 views
4

Je dois calculer combien de fois chaque mot-clé se reproduit dans une chaîne, avec le tri par nombre le plus élevé. Quel est l'algorithme le plus rapide disponible dans le code .NET à cette fin?Extrait les mots-clés du texte dans .NET

+0

Quelle langue? Je suis sûr qu'il n'y a pas de fonction cadre intégrée pour faire exactement cela, et les spécificités de la façon dont vous définissez "mot-clé" pourrait le compliquer, par ex. pluriels, ponctuation, etc. C'est un problème algorithmique intéressant mais la réponse dépendra du langage de programmation que vous utiliserez. –

+0

Les deux C# et VB.NET sont acceptables pour moi. Et actuellement, la capacité d'exclure des parties inutiles n'est pas nécessaire, tous les mots sont bons. – SharpAffair

Répondre

6

EDIT: le code ci-dessous regroupe des jetons uniques avec le nombre

string[] target = src.Split(new char[] { ' ' }); 

var results = target.GroupBy(t => new 
{ 
    str = t, 
    count = target.Count(sub => sub.Equals(t)) 
}); 

Cela commence enfin à faire plus de sens pour moi ...

EDIT: le code ci-dessous les résultats en nombre en corrélation avec substring cible:

string src = "for each character in the string, take the rest of the " + 
    "string starting from that character " + 
    "as a substring; count it if it starts with the target string"; 
string[] target = {"string", "the", "in"}; 

var results = target.Select((t, index) => new {str = t, 
    count = src.Select((c, i) => src.Substring(i)). 
    Count(sub => sub.StartsWith(t))}); 

Résultats est maintenant:

+  [0] { str = "string", count = 4 } <Anonymous Type> 
+  [1] { str = "the", count = 4 } <Anonymous Type> 
+  [2] { str = "in", count = 6 } <Anonymous Type> 

Code original ci-dessous:

string src = "for each character in the string, take the rest of the " + 
    "string starting from that character " + 
    "as a substring; count it if it starts with the target string"; 
string[] target = {"string", "the", "in"}; 

var results = target.Select(t => src.Select((c, i) => src.Substring(i)). 
    Count(sub => sub.StartsWith(t))).OrderByDescending(t => t); 

avec accusé reconnaissant à this previous response.

Les résultats de débogueur (qui ont besoin d'une logique supplémentaire pour inclure la chaîne correspondant à son compte):

-  results {System.Linq.OrderedEnumerable<int,int>}  
-  Results View Expanding the Results View will enumerate the IEnumerable 
     [0] 6 int 
     [1] 4 int 
     [2] 4 int 
+0

Maintenant c'est plutôt cool. –

+0

Oui, je dois revenir en arrière et upvote ma source. –

+0

Je me demande comment cela fonctionnerait par rapport à une méthode de force brute (par exemple, faire une boucle sur les mots-clés que vous recherchez, utiliser IndexOf pour trouver des occurrences et les compter dans un tableau de collecteurs)? Je ne veux en aucun cas enlever à l'awesomeness de cette solution, je suis simplement curieux puisque je n'ai pas un bon sens pour l'efficacité de linq. –

1

Vous pouvez diviser la chaîne en une collection de chaînes, une pour chaque mot, puis effectuer une requête LINQ sur la collection. Bien que je doute que ce soit le plus rapide, il serait probablement plus rapide que regex.

+0

J'ai mis en place des lecteurs de chaîne à passage unique avant de vérifier les occurrences de mots/caractères au fur et à mesure de la lecture. Vous voyez ce type de fonctions de code pour l'analyse CSV. – wllmsaccnt

4

J'sais au sujet le plus rapide, mais Linq est probablement le plus compréhensible:

var myListOfKeywords = new [] {"struct", "public", ...}; 

var keywordCount = from keyword in myProgramText.Split(new []{" ","(", ...}) 
    group by keyword into g 
    where myListOfKeywords.Contains(g.Key) 
    select new {g.Key, g.Count()} 

foreach(var element in keywordCount) 
    Console.WriteLine(String.Format("Keyword: {0}, Count: {1}", element.Key, element.Count)); 

Vous pouvez écrire ceci d'une manière non-Linq-y, mais le principe de base est le même; divisez la chaîne en mots et comptez les occurrences de chaque mot d'intérêt.

2

Algorithme simple: divisez la chaîne en un tableau de mots, parcourez ce tableau et stockez le nombre de chaque mot dans une table de hachage. Trier par nombre une fois terminé.