将数据分组到特定范围内

时间:2015-01-28 19:30:28

标签: c# .net

我有这个C#类:

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返回一个数组Option []。

现在我想要的是什么:

首先:按OptionType对选项进行分组

然后:通过SortOrder对第一组中的项目进行分组,条件是SortOrder在100-199之间的选项应该在一个组中,200-299在另一个组中,等等。

我能够做第一个:

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

或者

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

其次我不知道怎么做。我尝试添加另一个GroupBy但是没有用。当然做错了。

感谢。

更新: 我使用嵌套转发器工作,但我不确定这是否正确。

我使用上面的第一个查询获取选项:groupedOptions

将它绑定到Repeater。在该Repeater中显示OptionType。 在转发器的数据绑定事件中,我做了另一个分组:

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;

然后我将它绑定到具有checkboxlist的内部转发器。 这是我的整个.aspx测试页面。它是一个独立页面,可以通过将其放入asp.net webforms网站进行测试。

<%@ 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>

对不起,我仍然想要抓住Linq和GroupBy。

2 个答案:

答案 0 :(得分:1)

我会这样做:

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

您将获得像( "A", 1 ) ("B", 1) ("B", 2)这样的关键对象,并将原始对象作为值。

答案 1 :(得分:0)

我认为你可以这样做:

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

这样,您就拥有一个字典,其中键是OptionType,值是根据您的值范围的Option组。