Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use an anonymous type for this Linq grouping?

I have the following code which produces a dictionary containing multiple lists; each list can be retrieved with a numeric key.

public class myClass
{
    public string Group { get; set; }
    public int GroupIndex { get; set; }
    ...
}

public List<MyClass> myList { get; set; }

private Class IndexedGroup
{
    public int Index { get; set; }
    public IEnumerable<MyClass> Children { get; set; }
}

public Dictionary<int, IEnumerable<MyClass>> GetIndexedGroups(string group)
{
    return myList.Where(a => a.Group == group)
                 .GroupBy(n => n.GroupIndex)
                 .Select(g => new IndexedGroup { Index = g.Key, Children = g })
                 .ToDictionary(key => key.Index, value => value.Children);
}

Is there any way to eliminate the IndexedGroup class?

I've tried using an anonymous type in the Select method, like this:

.Select(g => new { Index = g.Key, Children = g })

but I get a type conversion error.

like image 548
Robert Harvey Avatar asked Feb 26 '23 15:02

Robert Harvey


2 Answers

Cast Children from IGrouping<T> to IEnumerable<T>, or explicitly pass generic parameters to the ToDictionary call.

The g parameter is an IGrouping<T>, which implements IEnumerable<T>.
The implicit generic calls end up creating a Dictionary<int, IGrouping<MyClass>>, which cannot be converted to a Dictionary<int, IEnumerable<MyClass>>.

This is avoided by your IndexedGroup class, since its Children property explicitly typed as IEnumerable<MyClass>.

For example:

return myList.Where(a => a.Group == group)
             .GroupBy(n => n.GroupIndex)
             .ToDictionary<int, IEnumerable<MyClass>>(g => g.Key, g => g);

Also, you may be interested in the ILookup<TKey, TElement> interface.

like image 96
SLaks Avatar answered Feb 28 '23 04:02

SLaks


You could just get rid of the Select() entirely and call .AsEnumerable():

return myList.Where(a => a.Group == group)
             .GroupBy(n => n.GroupIndex)
             .ToDictionary(g => g.Key, g => g.AsEnumerable());

Or you could change your return type to an ILookup, which is basically the data structure you're going for:

public ILookup<int, MyClass> GetIndexedGroups(string group)
{
    return myList.Where(a => a.Group == group)
                .ToLookup(n => n.GroupIndex);                    
}
like image 33
StriplingWarrior Avatar answered Feb 28 '23 04:02

StriplingWarrior