Reputation: 237
I am working on an MVC project. I need to return an object that groups menu items into groups of four to display in the view using foreach iteration. As this is a model being passed to the view, I need to return a non-generic collection class that can be bound on the .cshtml.
My thought is that I could group the list based on some type of count within LINQ to add four new List items to every Dictionary key. However, I haven't found an expression that would suffice to a Dictionary. I could solve this rather easily by creating another method and iterating again through the collection to assign keys based on a count, but it seems like unneeded iteration and bad practice.
Currently, I am working with the following query.
var itemsDict = rssDataContext.rss_Application_Blog_Category_Relationships
.Where(x => x.Application_Blog.rss_Application.ID == 1)
.Where(x => x.Blog_Category_ID == 1)
.Select(x => new MenuItem
{
Name = x.rss_Application_Blog.Blog_Title,
Uri = x.rss_Application_Blog.Blog_Uri,
ID = x.rss_Application_Blog.ID
});
But is there a way to group this query into groups of 4 class that be populated into Dictionary<int, List<MenuItem>>?
Upvotes: 1
Views: 488
Reputation: 1501163
I suspect you could do this:
var itemsDict = rssDataContext.rss_Application_Blog_Category_Relationships
.Where(x => x.Application_Blog.rss_Application.ID == 1)
.Where(x => x.Blog_Category_ID == 1)
.Select(x => new {
x.rss_Application_Blog.BlogTitle,
x.rss_Application_Blog.BlogUri,
x.rss_Application_Blog.ID
})
.AsEnumerable() // Do the rest of the query in-process
.Select((value, index) => new { value, index })
.ToLookup(pair => pair.index % 4,
pair => new MenuItem {
Name = pair.value.Blog_Title,
Uri = pair.value.Blog_Uri,
ID = pair.value.ID
});
Note that this returns a Lookup
rather than a Dictionary
, but that's actually a closer model for what you want.
Upvotes: 3
Reputation: 59923
@JonSkeet's solution is pretty good. Here's an alternative implementation using GroupBy to create the sublists and ToDictionary to project them into the final result:
var itemsDict = rssDataContext.rss_Application_Blog_Category_Relationships
.Where(x => x.Application_Blog.rss_Application.ID == 1)
.Where(x => x.Blog_Category_ID == 1)
.ToArray()
.Select((x, index) => new
{
Index = index,
Item = new MenuItem
{
Name = x.rss_Application_Blog.Blog_Title,
Uri = x.rss_Application_Blog.Blog_Uri,
ID = x.rss_Application_Blog.ID
}
});
.GroupBy(i => i.Index / 4)
.ToDictionary(g => g.Key);
The resulting sequence will look something like this:
items = new Dictionary<int, IGrouping<int>>()
{
0, new[]
{
new { Index = 0, Item = new MenuItem { ... } },
new { Index = 1, Item = new MenuItem { ... } }
}
1, new[]
{
new { Index = 2, Item = new MenuItem { ... } },
new { Index = 3, Item = new MenuItem { ... } }
}
};
Upvotes: 2