gbs
gbs

Reputation: 7266

Grouping data within particular range

I have this C# class:

public class Option
{
    public int OptionId { get; set; }
    public string OptionName { get; set; }
    public string OptionType { get; set; } //Three different types A,B,C
    public int SortOrder { get; set; } //100-199, 200-299, etc.
}

GetOptions returns an array Option[].

Now what I want:

First: Group the options by OptionType

Then: Group the items within the first group by SortOrder, with condition that option with SortOrder between 100-199 should be in one group, 200-299 in another and so forth.

I am able to do the first like:

IEnumerable<IGrouping<string, Option>> groupedOptions =
                       from option in options
                       group option by option.OptionType;

or this

 var groupedOptions2 = options.GroupBy(p=>p.OptionType);

Second I don't know how to. I tried adding another GroupBy but that didn't work. Sure doing something wrong.

Thanks.

Update: I got it working using nested repeater but am not really sure if that is the right way or not.

I get the options using the first query I have above: groupedOptions

Bind it to the Repeater. Display the OptionType in that Repeater. In the databound event of the repeater I do another grouping:

IGrouping<OptionType, Option> itm =(IGrouping<OptionType, Option>) e.Item.DataItem;
IEnumerable<IGrouping<int, Option>> nestedGroupedOptions =
     from option in itm
     group option by option.SortOrder/100;

Then I bind that to the inner repeater which has a checkboxlist. Here's my entire .aspx test page. It is a stand alone page and can be tested by dropping it inside an asp.net webforms website.

<%@ Page Language="C#" %>

<!DOCTYPE html>

<script runat="server">
    Dictionary<int, string> OptionGroupNames = null;
    protected void Page_Load(object sender, EventArgs e)
    {
        OptionGroupNames = GetOptionGroupNames();
        DisplayDrinks();
    }

    public void DisplayDrinks()
    {
        Option[] options = GetOptions();


        IEnumerable<IGrouping<OptionType, Option>> groupedOptions =
                   from option in options
                   group option by option.OptionType;

        rptrGroupOptions.DataSource = groupedOptions;
        rptrGroupOptions.DataBind();

    }

    protected void rptrGroupOptions_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            IGrouping<OptionType, Option> itm = (IGrouping<OptionType, Option>)e.Item.DataItem;
            Label lblHeader = e.Item.FindControl("lblOptionGroup") as Label;

            Repeater rptrOptions = e.Item.FindControl("rptrOptions") as Repeater;

            lblHeader.Text = itm.Key.ToString();

            IEnumerable<IGrouping<int, Option>> groupedOptions =
                       from option in itm
                       group option by option.SortOrder / 100;

            rptrOptions.DataSource = groupedOptions;
            rptrOptions.DataBind();

        }
    }

    protected void rptrOptions_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            IGrouping<int, Option> itm = (IGrouping<int, Option>)e.Item.DataItem;
            CheckBoxList cbl = e.Item.FindControl("cblOptions") as CheckBoxList;
            Label lblOptionGroup = e.Item.FindControl("lblOptionGroupNum") as Label;

            if (itm.Key != 1 && itm.Key != 2)
            {

                lblOptionGroup.Text = OptionGroupNames.First(p => p.Key == itm.Key).Value;
            }
            cbl.DataSource = itm;
            cbl.DataBind();
        }
    }

    public Option[] GetOptions()
    {
        var Options = new Option[]{
                new Option{OptionId=1, DisplayName="Green", OptionType = OptionType.Tea, SortOrder=100},
                new Option{OptionId=2, DisplayName="Black", OptionType = OptionType.Tea, SortOrder=101},

                new Option{OptionId=3, DisplayName="French", OptionType = OptionType.Coffee, SortOrder=202},
                new Option{OptionId=4, DisplayName="Espresso", OptionType = OptionType.Coffee, SortOrder=206},
                 new Option{OptionId=4, DisplayName="Cappuccino", OptionType = OptionType.Coffee, SortOrder=250},

                new Option{OptionId=1, DisplayName="Coke", OptionType = OptionType.Drinks, SortOrder=300},
                new Option{OptionId=2, DisplayName="Pepsi", OptionType = OptionType.Drinks, SortOrder=301},
                new Option{OptionId=3, DisplayName="Sprite", OptionType = OptionType.Drinks, SortOrder=302},

                new Option{OptionId=4, DisplayName="Apple Juice", OptionType = OptionType.Drinks, SortOrder=406},
                new Option{OptionId=1, DisplayName="Orange Juice", OptionType = OptionType.Drinks, SortOrder=400},

                new Option{OptionId=2, DisplayName="Wine", OptionType = OptionType.Drinks, SortOrder=501},
                new Option{OptionId=3, DisplayName="Beer", OptionType = OptionType.Drinks, SortOrder=502},
                new Option{OptionId=4, DisplayName="Rum", OptionType = OptionType.Drinks, SortOrder=520}
            };

        return Options.ToArray();
    }

    public static Dictionary<int, string> GetOptionGroupNames()
    {
        Dictionary<int, string> optionGroups = new Dictionary<int, string>();
        optionGroups.Add(1, "Tea");
        optionGroups.Add(2, "Coffee");
        optionGroups.Add(3, "Soda");
        optionGroups.Add(4, "Juice");
        optionGroups.Add(5, "Alcohol");

        return optionGroups;
    }

    public class Option
    {
        public int OptionId { get; set; }
        public string DisplayName { get; set; }
        public OptionType OptionType { get; set; } //Three different types A,B,C
        public int SortOrder { get; set; } //100-199, 200-299, etc.
    }

    public enum OptionType
    {
        Coffee,
        Tea,
        Drinks
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <asp:Repeater ID="rptrGroupOptions" runat="server" OnItemDataBound="rptrGroupOptions_ItemDataBound">
            <ItemTemplate>
                <asp:Label ID="lblOptionGroup" runat="server" ForeColor="Maroon"></asp:Label><br />
                <asp:Repeater ID="rptrOptions" runat="server" OnItemDataBound="rptrOptions_ItemDataBound">
                    <ItemTemplate>
                         <asp:Label ID="lblOptionGroupNum" runat="server" ForeColor="Sienna"></asp:Label>
                        <asp:CheckBoxList ID="cblOptions" runat="server" DataTextField="DisplayName" DataValueField="OptionId"></asp:CheckBoxList>
                    </ItemTemplate>
                </asp:Repeater>
                <br />
                </ItemTemplate>
        </asp:Repeater>
    </div>
    </form>
</body>
</html>

Sorry I am still trying to get hold of Linq and GroupBy.

Upvotes: 1

Views: 134

Answers (2)

ocuenca
ocuenca

Reputation: 39326

I think you could do something like this:

  var result= options.ToLookup(o => o.OptionType).
              ToDictionary(grouping => grouping.Key, grouping => grouping.
              ToLookup(o => o.SortOder/100));

This way, you have a dictionary where the key is the OptionType and the value is a group of Option according your range of values.

Upvotes: 0

loiti
loiti

Reputation: 168

I would do it like this way:

options.GroupBy(x => new { x.OptionType, Group = x.SortOder / 100 })

You will get key objects like ( "A", 1 ) ("B", 1) ("B", 2) with the original object as value.

Upvotes: 1

Related Questions