C # Frequency Distribution Ассоциативный контейнер инициализации - способ избежать хеширования дважды - PullRequest
0 голосов
/ 24 января 2019

Некоторый фон. Существует class Card, он имеет enum с именем RANK и член Rank типа RANK. Цель состоит в том, чтобы взять IEnumerable<Card> и создать словарь, подобный объекту, Key отредактированный RANK и Value d числом такого ранга в аргументированной последовательности. например. в контексте покера последовательность из пяти карт с четырьмя тузами выдает словарь вариантов {(ACE,4),(someOtherRank,1)}. Ниже приведена функция, которая у меня есть.

static IReadOnlyDictionary<Card.RANK, int> GetRankDistribution(IEnumerable<Card> hand)

    {
        var distribution = new Dictionary<Card.RANK, int>(13);

        foreach (Card.RANK rank in hand.Select(card => card.Rank))
        {
            distribution.TryGetValue(rank, out var valueBuffer);
            distribution[rank] = valueBuffer + 1;
        }

        return distribution;
    } 

Моя проблема в том, что эта функция вызывается чрезмерное количество раз, и, несмотря на то, что словарь имеет оптимальный размер для домена, я не могу придумать, как избежать хеширования дважды для создания объекта (один раз в TryGet и один раз для применить значение, независимо от того, увеличен ли он int() или функциональный ++).

В C ++ я мог бы ++dictionary[rank]; в теле цикла. Если Key отсутствует, он вставляется со стандартным значением Value, созданным на месте, и возвращается его ссылка (возможный операнд precrement ™).

В Python я мог бы просто return Counter(hand), и кто знает, что происходит, но это по крайней мере синтаксически элегантно.

Есть ли способ в C #, учитывая самый примитивный из типов значений, эффективно достичь того, что делает оператор карты C ++ [] (к лучшему или к худшему)?

Если в ответе участвуют наследование и рефакторинг, лично я не считаю его «эффективным», как я его определяю.

1 Ответ

0 голосов
/ 24 января 2019

Конечно:

var dictionary = hand.GroupBy(x => x.Rank).ToDictionary(x => x.Key, x => x.Count());
...