Найти самые встречающиеся слова в строке C # - PullRequest
8 голосов
/ 03 января 2012

Я пытаюсь найти вхождение слов в строку.

например,

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

из приведенной выше строки, я пытаюсь вычислить результаты примерно так:

  • world, 3
  • отлично, 2
  • привет, 1
  • this, 2

, но игнорируя любые слова сдлиной менее 3 символов, например, is, что встречалось дважды.

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

Ответы [ 5 ]

17 голосов
/ 03 января 2012

Использование 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())
6 голосов
/ 03 января 2012

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

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

Попробуйте что-то вроде этого

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));
3 голосов
/ 13 марта 2013

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

Пример:

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;
    }
}
3 голосов
/ 03 января 2012
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

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

1 голос
/ 03 января 2012
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;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...