patterncsharpMinor
Better way to group elements?
Viewed 0 times
elementswaybettergroup
Problem
this.Items is a list of products. Each product has a category (product.Attributes["category"]).I want to render a drop down list, where all the products are grouped by category.
This works well, but how could I improve it? Could there be a way to not use a dictionary?
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
var groups = new Dictionary>();
// sort by category
foreach (ListItem product in this.Items)
{
if (!groups.ContainsKey(category))
{
groups.Add(category, new List());
}
groups[category].Add(product);
}
// render each category
foreach (var group in groups)
{
//
RenderOptionGroupBeginTag(group.Key, writer);
// each option
group.Value.ForEach(p => this.RenderListItem(p, writer));
//
RenderOptionGroupEndTag(writer);
}
}Solution
Since
After you do that, you can use
Some other changes I made to the code:
ListItemCollection implements IEnumerable, but not IEnumerable, you have to use Cast before you can use other LINQ methods.After you do that, you can use
GroupBy, as Steve Michael suggested and then work with the result almost exactly like with your groups:var categoryGroups = this.Items.Cast()
.GroupBy(i => i.Attributes["category"]);
foreach (var categoryGroup in categoryGroups)
{
RenderOptionGroupBeginTag(group.Key, writer);
foreach (var item in group)
{
this.RenderListItem(item, writer);
}
RenderOptionGroupEndTag(writer);
}Some other changes I made to the code:
- I used
foreachinstead ofForEach().ForEach()looks like a LINQ method, but it behaves very differently, since it doesn't do any querying. I think that in cases like this,foreachin the most suitable option.
- Changing
groups(andgroup) tocategoryGroupsmeans that the code is clearer and so you can get rid of the loop comment.
- I also removed the other comments, because I think the code is clear about what it does. If you want to emphasize that
RenderOptionGroupBeginTagcreates `, maybe you should rename it? Probably to something likeRenderOptgroupBeginTag`.
Code Snippets
var categoryGroups = this.Items.Cast<ListItem>()
.GroupBy(i => i.Attributes["category"]);
foreach (var categoryGroup in categoryGroups)
{
RenderOptionGroupBeginTag(group.Key, writer);
foreach (var item in group)
{
this.RenderListItem(item, writer);
}
RenderOptionGroupEndTag(writer);
}Context
StackExchange Code Review Q#64261, answer score: 3
Revisions (0)
No revisions yet.