More than once I've been writing code using LINQs
GroupBy and
ToDictionary methods with a feeling that the code didn't become as clear as I wanted it to be. I did some web searching, hoping that there might exist a third party library with a smart solution, but what I found though, was that I didn't even have to install another library, LINQ already contained a method for it!
I'll try to show you how
ToLookup can be useful with a phony example.
Example
Suppose a group of smurfs take turn rolling a die and want us to print the result on the screen, like this:
Smurfs that rolled a 1
- Grouchy Smurf
- Greedy Smurf
Smurfs that rolled a 2
- Smurfette
Smurfs that rolled a 3
- Papa Smurf
- Hefty Smurf
Smurfs that rolled a 4
Smurfs that rolled a 5
- Brainy Smurf
Smurfs that rolled a 6
- Clumsy Smurf
For this I use a class to store each result in:
class DieRollResult
{
public string Player { get; set; }
public int Value { get; set; }
}
And a list to store all the results of a round in:
var resultList = new List<DieRollResult>()
{
new DieRollResult{ Player= "Papa Smurf", Value = 3},
new DieRollResult{ Player= "Smurfette", Value = 2},
new DieRollResult{ Player= "Hefty Smurf", Value = 3},
new DieRollResult{ Player= "Brainy Smurf", Value = 5},
new DieRollResult{ Player= "Grouchy Smurf", Value = 1},
new DieRollResult{ Player= "Clumsy Smurf", Value = 6},
new DieRollResult{ Player= "Greedy Smurf", Value = 1},
};
A solution using GroupBy
Notice the usage of SingleOrDefault to find the right group, it isn't possible to find it by using an index.
Notice also that using this result set no smurf rolled a 4, and because empty groups like this are allowed a null check has to be done before iterating through the group to avoid a NullReferenceException.
A solution using GroupBy combined with ToDictionary
This time, notice the rather verbose expression to assign the variable resultGroups.
Notice also that this time, the group can be fetched using an index, but we still have to check if the dictionary really contains that index key to avoid a KeyNotFoundException.
A solution using ToLookup
So, finally, by using the
ToLookup method, the assignment of the variable
resultGroups is as short and clear as in the
GroupBy example.
It is also possible to use an index to get the right group to iterate through. And since the
ILookup object just returns an empty
IEnumerable when it is indexed with a key that it doesn't contain, there is no need to check for null or if the key exists like we had to do in the other examples!
This is why I like the ToLookup method, it raises the signal-to-noise ratio a tiny bit, but sometimes it is just that small improvement that can make the code clearer.
On the downside though, the method seems to be used so seldom that I think few programmers have seen it, so using it might make the code break the "
Principle of least surprise".