2012-01-03 3 views
6

Я пытаюсь найти верхние вхождения слов в строке.Найти самые высокие слова в строке C#

например.

Hello World This is a great world, This World is simply great 

из приведенных выше строк я пытаюсь вычислить результаты что-то вроде следующим образом:

  • мира, 3
  • большого, 2
  • Здравствуйте, 1
  • это, 2

, но игнорирование любых слов длиной менее 3 символов например, is, который произошел дважды.

Я попытался заглянуть в пары Dictionary<key, value>, я попытался изучить расширение linq's GroupBy. Я знаю, что решение лежит где-то посередине, но я просто не могу обойти алгоритм и как это сделать.

+4

ли это домашнее задание? – dasblinkenlight

+0

Это похоже: http://stackoverflow.com/questions/8630235/finding-the-number-of-occurences-strings-in-a-specific-format-occur-in-a-given-t/8630247#8630247 – Matthias

+0

@dasblinkenlight - Нет, это не домашнее задание, я пытаюсь извлечь мета-ключевые слова и сохранить в базе данных для каждой записи. – Thr3e

ответ

14

Использование LINQ и Regex

Regex.Split("Hello World This is a great world, This World is simply great".ToLower(), @"\W+") 
    .Where(s => s.Length > 3) 
    .GroupBy(s => s) 
    .OrderByDescending(g => g.Count()) 
+3

отличный ответ, но я бы не рекомендовал это решение, ему было бы лучше понять использование словаря, а не регулярное выражение или linq. просто говорю. – DarthVader

+0

+1 Лучший ответ, поскольку он принимает во внимание пунктуацию ... – xandercoded

+0

@DarthVader Я согласен на математическом уровне. С точки зрения программирования знание LINQ столь же ценно. –

0
string words = "Hello World This is a great world, This World is simply great".ToLower(); 

var results = words.Split(' ').Where(x => x.Length > 3) 
           .GroupBy(x => x) 
           .Select(x => new { Count = x.Count(), Word = x.Key }) 
           .OrderByDescending(x => x.Count); 

foreach (var item in results) 
    Console.WriteLine(String.Format("{0} occured {1} times", item.Word, item.Count)); 

Console.ReadLine(); 

Чтобы получить слово с наибольшим числом вхождений:

results.First().Word;

+0

Вместо 'Word = x.First()' вы можете получить доступ к групповому ключу через 'Word = x.Key'. –

+0

Спасибо @TathamOddie не знал этого - * btw *, спасибо за FormsAuthenticationExtensions;) – xandercoded

3
const string input = "Hello World This is a great world, This World is simply great"; 
var words = input 
    .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) 
    .Where(w => w.Length >= 3) 
    .GroupBy(w => w) 
    .OrderByDescending(g => g.Count()); 

foreach (var word in words) 
    Console.WriteLine("{0}x {1}", g.Count(), word.Key); 

// 2x World 
// 2x This 
// 2x great 
// 1x Hello 
// 1x world, 
// 1x simply 

Не идеальный, потому что она не подрезать запятой , но он показывает вам, как сделать группировку и фильтрацию по крайней мере.

3

Так что я бы избегал LINQ и Regex и т. Д., Поскольку кажется, что вы пытаетесь найти алгоритм и понимаете, что не используйте какую-либо функцию для этого.

Не то, чтобы это были не допустимые решения. Они есть. Определенно.

Try что-то вроде этого

Dictionary<string, int> dictionary = new Dictionary<string, int>(); 

string sInput = "Hello World, This is a great World. I love this great World"; 
sInput = sInput.Replace(",", ""); //Just cleaning up a bit 
sInput = sInput.Replace(".", ""); //Just cleaning up a bit 
string[] arr = sInput.Split(' '); //Create an array of words 

foreach (string word in arr) //let's loop over the words 
{ 
    if (word.Length >= 3) //if it meets our criteria of at least 3 letters 
    { 
     if (dictionary.ContainsKey(word)) //if it's in the dictionary 
      dictionary[word] = dictionary[word] + 1; //Increment the count 
     else 
      dictionary[word] = 1; //put it in the dictionary with a count 1 
    } 
} 

foreach (KeyValuePair<string, int> pair in dictionary) //loop through the dictionary 
    Response.Write(string.Format("Key: {0}, Pair: {1}<br />",pair.Key,pair.Value)); 
+0

Вы можете сделать string sInput = "Hello World, Это великий мир. Я люблю этот великий мир"; string sInput = "Hello World, это великий мир. Я люблю этот великий мир" .ToLower(); , чтобы сделать регистр нечувствительным. Лично мне нравится чувствительность к регистру, так как он может рассказать вам о существительных и начале предложения, даже без пунктуации, поэтому ничего не потеряно. С другой стороны, мир и мир не равны. – Jordan

+0

+1 Хороший учебный пост. Если бы я мог, дал бы еще +1 для комментариев. –

+1

Что касается вашего комментария к корпусу, есть гораздо более простое решение: создать словарь с помощью нечувствительного к регистру сравнения: 'var dictionary = new Dictionary (StringComparer.InvariantCultureIgnoreCase);' –

2

Я пишу процессор строки class.You может использовать его.

Пример:

metaKeywords = bodyText.Process(blackListWords: prepositions).OrderByDescending().TakeTop().GetWords().AsString(); 

Класс:

public static class StringProcessor 
{ 
    private static List<String> PrepositionList; 

    public static string ToNormalString(this string strText) 
    { 
     if (String.IsNullOrEmpty(strText)) return String.Empty; 
     char chNormalKaf = (char)1603; 
     char chNormalYah = (char)1610; 
     char chNonNormalKaf = (char)1705; 
     char chNonNormalYah = (char)1740; 
     string result = strText.Replace(chNonNormalKaf, chNormalKaf); 
     result = result.Replace(chNonNormalYah, chNormalYah); 
     return result; 
    } 

    public static List<KeyValuePair<String, Int32>> Process(this String bodyText, 
     List<String> blackListWords = null, 
     int minimumWordLength = 3, 
     char splitor = ' ', 
     bool perWordIsLowerCase = true) 
    { 
     string[] btArray = bodyText.ToNormalString().Split(splitor); 
     long numberOfWords = btArray.LongLength; 
     Dictionary<String, Int32> wordsDic = new Dictionary<String, Int32>(1); 
     foreach (string word in btArray) 
     { 
      if (word != null) 
      { 
       string lowerWord = word; 
       if (perWordIsLowerCase) 
        lowerWord = word.ToLower(); 
       var normalWord = lowerWord.Replace(".", "").Replace("(", "").Replace(")", "") 
        .Replace("?", "").Replace("!", "").Replace(",", "") 
        .Replace("<br>", "").Replace(":", "").Replace(";", "") 
        .Replace("،", "").Replace("-", "").Replace("\n", "").Trim(); 
       if ((normalWord.Length > minimumWordLength && !normalWord.IsMemberOfBlackListWords(blackListWords))) 
       { 
        if (wordsDic.ContainsKey(normalWord)) 
        { 
         var cnt = wordsDic[normalWord]; 
         wordsDic[normalWord] = ++cnt; 
        } 
        else 
        { 
         wordsDic.Add(normalWord, 1); 
        } 
       } 
      } 
     } 
     List<KeyValuePair<String, Int32>> keywords = wordsDic.ToList(); 
     return keywords; 
    } 

    public static List<KeyValuePair<String, Int32>> OrderByDescending(this List<KeyValuePair<String, Int32>> list, bool isBasedOnFrequency = true) 
    { 
     List<KeyValuePair<String, Int32>> result = null; 
     if (isBasedOnFrequency) 
      result = list.OrderByDescending(q => q.Value).ToList(); 
     else 
      result = list.OrderByDescending(q => q.Key).ToList(); 
     return result; 
    } 

    public static List<KeyValuePair<String, Int32>> TakeTop(this List<KeyValuePair<String, Int32>> list, Int32 n = 10) 
    { 
     List<KeyValuePair<String, Int32>> result = list.Take(n).ToList(); 
     return result; 
    } 

    public static List<String> GetWords(this List<KeyValuePair<String, Int32>> list) 
    { 
     List<String> result = new List<String>(); 
     foreach (var item in list) 
     { 
      result.Add(item.Key); 
     } 
     return result; 
    } 

    public static List<Int32> GetFrequency(this List<KeyValuePair<String, Int32>> list) 
    { 
     List<Int32> result = new List<Int32>(); 
     foreach (var item in list) 
     { 
      result.Add(item.Value); 
     } 
     return result; 
    } 

    public static String AsString<T>(this List<T> list, string seprator = ", ") 
    { 
     String result = string.Empty; 
     foreach (var item in list) 
     { 
      result += string.Format("{0}{1}", item, seprator); 
     } 
     return result; 
    } 

    private static bool IsMemberOfBlackListWords(this String word, List<String> blackListWords) 
    { 
     bool result = false; 
     if (blackListWords == null) return false; 
     foreach (var w in blackListWords) 
     { 
      if (w.ToNormalString().Equals(word)) 
      { 
       result = true; 
       break; 
      } 
     } 
     return result; 
    } 
} 
Смежные вопросы