dotnetnoob
dotnetnoob

Reputation: 11330

Linq - Group by first letter of name

I'm using Entity Framework 6 as my data source.

I've created a page that will list suppliers by the first letter of their name, so first we have all the 'A's, then 'B's and so on.

In order to do this, I use 2 ListView objects - it could easily be a Repeater, but that's not important.

Although my list of suppliers is not extensive, the method I've used to get the data is quite expensive in that I have to call it 27 times during databinding. I'm pretty sure there is a better way of going about this but don't know my way around Linq well enough.

I'm thinking there must be a way of grouping data and then looping through the content of a group.

Here is the important bits of code. The linq to retreive the child data and the databinding code:

    public static IEnumerable<Supplier> StartsWith(string firstLetter)
    {
        return Select() // select simply returns all data for the entity
            .Where(x => x.Name.StartsWith(firstLetter, StringComparison.OrdinalIgnoreCase));
    }

    protected void ListViewAtoZ_ItemDataBound(object source, ListViewItemEventArgs e)
    {
        var item = e.Item;

        if (item.ItemType == ListViewItemType.DataItem)
        {
            var alphanumeric = (string)item.DataItem;

            var h2 = item.GetControl<HtmlGenericControl>("HtmlH2", true);
            h2.InnerText = alphanumeric;

            var childView = item.GetControl<ListView>("ListViewStartsWith", true);
            childView.DataSource = LenderView.StartsWith(alphanumeric);
            childView.DataBind();
        }
    }

    protected void ListViewStartsWith_ItemDataBound(object source, ListViewItemEventArgs e)
    {
        var item = e.Item;

        if (item.ItemType == ListViewItemType.DataItem)
        {
            var supplier = (Supplier)item.DataItem;

            var litName = item.GetControl<Literal>("LiteralName", true);
            litName.Text = supplier.Name;
        }
    }

    void LoadData()
    {
        var alphanumerics = new string[]
        {
            "0 - 9","A","B","C","D","E","F","G","H","I","J","K","L",
            "M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"
        }; 

        ListViewAtoZ.DataSource = alphanumerics;
        ListViewAtoZ.DataBind();
    }

Upvotes: 8

Views: 8235

Answers (2)

Parthasarathy
Parthasarathy

Reputation: 2818

You can use the following to group and get the sub list of items.

Select().GroupBy(x => x.Name.Substring(0,1).ToUpper(), (alphabet, subList) => new { Alphabet = alphabet, SubList = subList.OrderBy(x => x.Name).ToList() })
                .OrderBy(x => x.Alphabet)

The above code should group all the data in a single iteration. The code works for LINQ to objects. It should work the same way for LINQ to entities also.

Upvotes: 15

Jenish Rabadiya
Jenish Rabadiya

Reputation: 6766

I'm thinking there must be a way of grouping data and then looping through the content of a group.

Yes there are. Try something like following

Select().GroupBy(c=>string.IsNullOrEmpty(c.Name) ? '' : c.Name[0]);

Just added string.IsNullOrEmpty to make sure string is not null.

Upvotes: 1

Related Questions