5
\$\begingroup\$

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 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,
 "DisplayName": "Orange Juice",
 "OptionType": 2,
 "SortOrder": 400,
 "OptionGroupName": "Fruit"
 }
 ]
 },
 {
 "SortOrderGroup": 5,
 "GroupName": "Alcohol",
 "SubGroup": [
 {
 "OptionId": 2,
 "DisplayName": "Wine",
 "OptionType": 2,
 "SortOrder": 501,
 "OptionGroupName": "Alcohol"
 },
 {
 "OptionId": 3,
 "DisplayName": "Beer",
 "OptionType": 2,
 "SortOrder": 502,
 "OptionGroupName": "Alcohol"
 },
 {
 "OptionId": 4,
 "DisplayName": "Rum",
 "OptionType": 2,
 "SortOrder": 520,
 "OptionGroupName": "Alcohol"
 }
 ]
 }
]
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 22, 2015 at 2:46
\$\endgroup\$

1 Answer 1

8
\$\begingroup\$

So we're looking at a LINQ query:

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<T> 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<T> :)

GetOptions shouldn't be returning an array (a concrete type) - it should return an abstraction - IEnumerable<T> in this case.

answered Mar 23, 2015 at 18:17
\$\endgroup\$
1
  • 1
    \$\begingroup\$ The GetOptions is a 3rd party service call that returns an Array. I will try out your suggestion. \$\endgroup\$ Commented Mar 23, 2015 at 20:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.