Some background. There is a class Card
, it has an enum
called RANK
, and a member Rank
of type RANK
. The goal is to take an IEnumerable<Card>
, and produce a dictionary like object, Key
ed by RANK
and Value
d by the number of such rank in the argued sequence. eg. in the context of Poker, a five card sequence with quad Aces would yield an order-variant {(ACE,4),(someOtherRank,1)}
dictionary. Below is the function that I have.
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;
}
My problem is this function is called an inordinate amount of times, and allthough the dictionary is optimally sized for the domain, I cannot conceive of a way to avoid hashing twice to build the object(once in the TryGet, and once to apply the value, whether incremented off int()
or a functional ++
).
In C++, I could ++dictionary[rank];
in the loop body. If the Key
is absent, it is inserted, with the default Value
constructed in situ, and its reference returned(the eventual operand of the precrement™).
In Python, I could just return Counter(hand)
, and who knows what happens, but it is at least syntactically elegant.
Is there any way in C#, given the most primitive of value types, to effectively achieve what the C++ map operator[](for better or worse) does?
If inheriting and refactoring are involved in the answer, I personally do not consider it 'effective' as I define it.
当然:
var dictionary = hand.GroupBy(x => x.Rank).ToDictionary(x => x.Key, x => x.Count());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.