patterncsharpMinor
Grouping queries
Viewed 0 times
queriesgroupingstackoverflow
Problem
I have a list of Options. From that list:
-
First I want to get only Drink (the where clause).
-
Then I want to group them by their
-
I can stop there and loop through the items and create checkboxes for each items. But I got a requirement that if the OptionGroupName=Alcohol then I need to create radio list instead of checkboxes.
Here's the code that does grouping using Linq:
Here's the JSON I get. That's what I want:
So now I can check on client-side if GroupName="Alcohol" generate radio buttons else generate checkboxes.
```
[
{
"SortOrderGroup": 3,
"GroupName": "Soft",
"SubGroup": [
{
"OptionId": 1,
"DisplayName": "Coke",
"OptionType": 2,
"SortOrder": 300,
"OptionGroupName": "Soft"
},
{
"OptionId": 2,
"DisplayName": "Pepsi",
"OptionType": 2,
"SortOrder": 301,
"OptionGroupName": "Soft"
},
{
"OptionId": 3,
"DisplayName": "Sprite",
"OptionType": 2,
"SortOrder": 302,
"OptionGroupName": "Soft"
}
]
},
{
"SortOrderGroup": 4,
"GroupName": "Fruit",
"SubGroup": [
{
"OptionId": 4,
"DisplayName": "Apple Juice",
"OptionType": 2,
"SortOrder": 406,
"OptionGroupName": "Fruit"
},
{
"OptionId": 1,
"DisplayN
-
First I want to get only Drink (the where clause).
-
Then I want to group them by their
SortOrder (range of 100).-
I can stop there and loop through the items and create checkboxes for each items. But I got a requirement that if the OptionGroupName=Alcohol then I need to create radio list instead of checkboxes.
Here's the code that does grouping using Linq:
Option[] options = GetOptions();
var groupedOptions = from option in options
where option.OptionType == OptionType.Drinks
group option by option.SortOrder / 100 into grouped
select new {
SortOrderGroup = grouped.Key,
GroupName = grouped.FirstOrDefault().OptionGroupName
,SubGroup= grouped
};Here's the JSON I get. That's what I want:
So now I can check on client-side if GroupName="Alcohol" generate radio buttons else generate checkboxes.
```
[
{
"SortOrderGroup": 3,
"GroupName": "Soft",
"SubGroup": [
{
"OptionId": 1,
"DisplayName": "Coke",
"OptionType": 2,
"SortOrder": 300,
"OptionGroupName": "Soft"
},
{
"OptionId": 2,
"DisplayName": "Pepsi",
"OptionType": 2,
"SortOrder": 301,
"OptionGroupName": "Soft"
},
{
"OptionId": 3,
"DisplayName": "Sprite",
"OptionType": 2,
"SortOrder": 302,
"OptionGroupName": "Soft"
}
]
},
{
"SortOrderGroup": 4,
"GroupName": "Fruit",
"SubGroup": [
{
"OptionId": 4,
"DisplayName": "Apple Juice",
"OptionType": 2,
"SortOrder": 406,
"OptionGroupName": "Fruit"
},
{
"OptionId": 1,
"DisplayN
Solution
So we're looking at a LINQ query:
You went with query syntax - let's see what the method syntax would look like:
The
...but then, you already have an
I'd probably write your query like this:
Notice I don't care what type
Option[] options = GetOptions();
var groupedOptions = from option in options
where option.OptionType == OptionType.Drinks
group option by option.SortOrder / 100 into grouped
select new {
SortOrderGroup = grouped.Key,
GroupName = grouped.FirstOrDefault().OptionGroupName
,SubGroup= grouped
};You went with query syntax - let's see what the method syntax would look like:
var options = GetOptions(); // some IEnumerable - who cares that it's an array?
options.Where(option => option.OptionType == OptionType.Drinks)
.GroupBy(option => option.SortOrder / 100)
.Select(grouped => new
{
Grouping = grouped.Key,
Name = grouped.FirstOrDefault().OptionGroupName),
SubGroup = grouped
});The
FirstOrDefault() call will return a null when grouped has no items - that's not really a possibility here, but just because FirstOrDefault itself can return a null, accessing .OptionGroupName on it looks like it's asking for a NullReferenceException. It would be better to use .First() here, because you know a group only exists when it has at least one item......but then, you already have an
OptionGroupName for each item - why bother selecting the .First at all?I'd probably write your query like this:
options.Where(option => option.OptionType == OptionType.Drinks)
.GroupBy(option => new
{
SortOrder = option.SortOrder / 100, // integer division
GroupName = option.OptionGroupName
})
.Select(grouping => new
{
SortOrder = grouping.Key.SortOrder,
Name = grouping.Key.GroupName,
SubGroup = grouping
});Notice I don't care what type
GetOptions() is returning - all I'm interested in, is that whatever it's returning implements IEnumerable so that I can LINQ over it - and the plural name is all I need to see to infer I'm dealing wiht an IEnumerable :)GetOptions shouldn't be returning an array (a concrete type) - it should return an abstraction - IEnumerable in this case.Code Snippets
Option[] options = GetOptions();
var groupedOptions = from option in options
where option.OptionType == OptionType.Drinks
group option by option.SortOrder / 100 into grouped
select new {
SortOrderGroup = grouped.Key,
GroupName = grouped.FirstOrDefault().OptionGroupName
,SubGroup= grouped
};var options = GetOptions(); // some IEnumerable - who cares that it's an array?
options.Where(option => option.OptionType == OptionType.Drinks)
.GroupBy(option => option.SortOrder / 100)
.Select(grouped => new
{
Grouping = grouped.Key,
Name = grouped.FirstOrDefault().OptionGroupName),
SubGroup = grouped
});options.Where(option => option.OptionType == OptionType.Drinks)
.GroupBy(option => new
{
SortOrder = option.SortOrder / 100, // integer division
GroupName = option.OptionGroupName
})
.Select(grouping => new
{
SortOrder = grouping.Key.SortOrder,
Name = grouping.Key.GroupName,
SubGroup = grouping
});Context
StackExchange Code Review Q#84698, answer score: 8
Revisions (0)
No revisions yet.