I'm not sure this question fits in StackOverflow. If that's the case, please let me know.
I'm trying to create a Lookup<,>
from an IEnumerable<IGrouping<,>>
, just for the sake of it (this isn't an XY problem).
My understanding is that the only way to create a Lookup
object is with the ToLookup
method.
The best way I found to do this is to separate the groupings into key-value pairs with duplicate keys and then group it again into a Lookup
using ToLookup
:
groups // IEnumerable<IGrouping<TKey, TElement>>
.SelectMany(group => group.Select(item => new KeyValuePair<TKey, TElement>(group.Key, item)))
.ToLookup(kvp => kvp.Key, kvp => kvp.Value)
I think this is very inefficient because it separates the groups and then 'reassembles' them, instead of taking advantage of the fact that they're already grouped.
Is there a better way to do this?
Possible use case:
Let's say we have a list of names. We want to group the names by their first letter, so far so good, but we only want to keep groups with more than two names, and we want the result to be a Lookup<,>
so we'll have access to its useful indexer.
The first part can be done easily:
names.GroupBy(name => name[0]).Where(group => group.Count() > 2)
But then we will need to convert the IEnumerable<IGrouping<char, string>>
to a Lookup<char, string>
.
What reasons there are for not having a constructor equivalent to Dictionary<TKey, TValue>(IEnumerable<KeyValuePair<TKey, TValue>>)
?
In addition to the possible reasons that could explain why such functionality is not available that Marc pointed out, I just wanted to add that the indexer is also available in Dictionary, so you could create a IDictionary<char, IEnumerable<string>>
and then keep in mind that you will get an Exception if you use the indexer with a key that's not in the dictionary (which is an important difference with the indexer in the ILookup
... in addition to the Lookup being immutable in contrast to the dictionary).
So you could do something like this:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var names = new List<string>();
names.Add("Agustin");
names.Add("Alejandro");
names.Add("Diego");
names.Add("Damian");
names.Add("Dario");
IDictionary<char, IEnumerable<string>> fakeLookup = names.GroupBy(name => name[0])
.Where(group => group.Count() > 2)
.ToDictionary(group => group.Key, group => group.AsEnumerable());
foreach(var name in fakeLookup ['D'])
{
Console.WriteLine(name);
}
var namesStartingWithA = lookup['A']; // This will throw a KeyNotFoundException
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With