Подсчет количества символов

Я написал код, который использует SortedDictionary, чтобы подсчитать количество вхождений символа в строке.

Как я могу улучшить этот код? Что я должен делать по-другому? Любые советы вообще были бы полезны.

    static void Main(string[] args)
    {
        string longText = @"The quick brown fox jumps over the lazy dog";

        var count = CharacterCount.Count(longText);

        foreach (var character in count)
        {
            Console.WriteLine("{0} - {1}", character.Key, character.Value);
        }
    }

Класс CharacterCount:

class CharacterCount
{
    public static SortedDictionary<char, ulong> Count(string stringToCount)
    {
        SortedDictionary<char, ulong> characterCount = new SortedDictionary<char, ulong>();

        foreach (var character in stringToCount)
        {
            if (!characterCount.ContainsKey(character))
            {
                characterCount.Add(character, 1);
            }
            else
            {
                characterCount[character]++;
            }
        }

        return characterCount;
    }

Вот результат:

введите описание изображения здесь

11 голосов | спросил user9993 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 25 Sep 2014 18:41:15 +0400 2014, 18:41:15

5 ответов


13

Вы можете сделать то же самое с LINQ :

var counts = longText.GroupBy(c => c) // put each character into a "bucket"
                     // order the buckets alphabetically
                     .OrderBy(c => c.Key);
                     // then convert to dictionary where key = character, value = count
                     .ToDictionary(grp => grp.Key, grp => grp.Count()) 

Для удобства /удобочитаемости вы можете превратить это в метод расширения в string:

static class Extensions 
{
    public static Dictionary<char, int> CharacterCount(this string text)
    {
        return text.GroupBy(c => c)
                   .OrderBy(c => c.Key)
                   .ToDictionary(grp => grp.Key, grp => grp.Count());
    }
}

И вызовите его вот так:

var longText = @"The quick brown fox jumps over the lazy dog";

var counts = longText.CharacterCount();

Однако обратите внимание, что вышеописанный не создает словарь отсортированный в том смысле, что если впоследствии вы добавите ему еще один ключ /значение, заказ больше не будет поддерживаться. Вы можете повторно сортировать в этот момент или использовать этот SortedDictionary , чтобы создать отсортированный словарь.

ответил Adam Lear 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 25 Sep 2014 19:27:23 +0400 2014, 19:27:23
5

Вы можете избавиться от переменной count, поскольку она здесь не нужна и просто добавляет беспорядок в main, вы просто вызываете метод .Count внутри объявление foreach.

, так что:

static void Main(string[] args)
{
    string longText = @"The quick brown fox jumps over the lazy dog";

    var count = CharacterCount.Count(longText);

    foreach (var character in count)
    {
        Console.WriteLine("{0} - {1}", character.Key, character.Value);
    }
}

становится этим

static void Main(string[] args)
{
    string longText = @"The quick brown fox jumps over the lazy dog";

    foreach (var character in CharacterCount.Count(longText))
    {
        Console.WriteLine("{0} - {1}", character.Key, character.Value);
    }
}
ответил Malachi 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 25 Sep 2014 19:48:57 +0400 2014, 19:48:57
4

Вы используете ulong в вашем SortedDictionary<T,TK>, это представляет собой максимальное значение 18 446 744 073 709 551 615, что, по-видимому, немного завышено для вашей ситуации. Я уверен, что int будет достаточно, так как максимальное значение равно 2 147 483 647.

Кроме того, ваш метод с именем Count, трудно предположить, что он вернет код SortedDictionary<char,ulong>. Я думаю, что он вернет код int, так как все методы с именем Count в .Net Framework. Вы можете назвать его GetNumberOfOccurencePerCharacter, в противном случае это выглядит как Count вернет число символов в string вместо количества раз, когда каждый символ появляется в string

ответил IEatBagels 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 25 Sep 2014 23:03:07 +0400 2014, 23:03:07
4

Есть одна фундаментальная вещь, которую этот код не обрабатывает. Хотя вы, возможно, выбрали это ограничение по назначению, многие люди не совсем осознают это, поэтому я подниму его. Существует фундаментальное различие между «символом» и ---- +: = 0 =: + ----. Ваш вопрос и код рассматривают их как одно и то же. Что может быть хорошо для ваших целей, но не будет обрабатывать все возможные символы в Юникоде.

В Unicode то, что люди обычно считают персонажем, называется grapheme. Каждая графема представлена ​​одним или несколькими последовательными значениями char. Некоторые графемы даже имеют несколько возможных представлений. В .NET на самом деле очень просто выделить строку в своих графемах, используя StringInfo. GetTextElementEnumerator . Но это касается только первого предостережения. Второе предупреждение (несколько представлений) можно обработать с помощью String.Normalize .

Я считаю, что эти вызовы могут быть объединены с подходом LINQ, предложенным Анной Лир, но я еще не подтвердил, собрав его вместе.

(См. также мой соответствующий ответ по аналогичному вопросу.)

ответил Michael Urman 27 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowSat, 27 Sep 2014 17:05:22 +0400 2014, 17:05:22
1

Хотя этот вопрос устарел, никто не упомянул, что с помощью ContainsKey() вместе с получателем свойства Item Dictionary<TKey, TValue> следует заменить вызовом TryGetValue(), который быстрее потому что проверка, существует ли ключ, также выполняется с помощью Item getter.

Внутри этих трех методов вызывается FindEntry() , чтобы проверить, существует ли данный ключ. Поэтому вызов этого метода только один раз через метод TryGetValue() должен быть таким, как это сделать

public static SortedDictionary<char, int> Count(string stringToCount)
{
    SortedDictionary<char, int> characterCount = new SortedDictionary<char, int>();

    foreach (var character in stringToCount)
    {
        int counter = 0
        characterCount.TryGetValue(character, out counter);
        characterCount[character] = counter +1;
    }

    return characterCount;
}

Я изменил тип TValue словаря на int, потому что этого достаточно.

ответил Heslacher 4 FebruaryEurope/MoscowbThu, 04 Feb 2016 12:19:23 +0300000000pmThu, 04 Feb 2016 12:19:23 +030016 2016, 12:19:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132