简体   繁体   中英

GroupBy equivalent for Windows Phone

I'm currently creating Win8 & Wp8 apps using shared portable class libraries. One of the first things I do is get a list of offers.

public class Offer
{
    string category;
    ....
}

Each of these offers has one of a finite number of categories assigned to it. In my Win8 app, once I get the list of offers I am able to group these offers by category .

var groupedOffers = offers.Items.GroupBy(item => item.category).OrderBy(item => item.Key.ToString());

Unfortunately the same functionality isn't available in Wp8, or else it's not obvious. Anybody know how to achieve the same thing without explicitly looping through and creating the groups?

var group = from p in offers.Items                        
group p by p.category into g
                    select g

offers.Items = group.ToList<Item>()

Hope this will help you or at-least give you some idea

Make sure you've got a 'using System.Linq' at the top of your class.

It could be a limitation imposed by a query provider. Try this:

var groupedOffers = offers.Items
      .GroupBy(item => item.category)
      .AsEnumerable()
      .OrderBy(item => item.Key.ToString());

or this:

var groupedOffers = offers.Items
      .AsEnumerable()
      .GroupBy(item => item.category)
      .OrderBy(item => item.Key.ToString());

The AsEnumerable() will cause the remainder of the query to be processed as Linq-to-Objects. This can have a negative performance, IO and/or memory penalty, but it's necessary from time to time. For example, imagine you're using EF against a SQL Server.

  1. var newborns = Context.People.Where(x => x.DateOfBirth.CompareTo(today) == 0);
  2. var newborns = Context.People.AsEnumerable().Where(x => x.DateOfBirth.CompareTo(today) == 0);

The first query will get translated into something similar to "SELECT * FROM People WHERE DateOfBirth = '2014-01-31'" where the second will translate into "SELECT * FROM People". Then LINQ will filter the entire set of people to only yield the results whose DateOfBirth.CompareTo(today) == 0. If the database contained a lot of data, lived in a datacenter far away, etc., that would mean streaming the entire set of data to answer 1 simple query. 1 would be more efficient b/c the filtering would happen at the source and only the matching data would stream back to your .NET code.

Without the AsEnumerable, it's up to the LINQ query provider to attempt to convert your LINQ expression into a query that makes sense to the system you're querying (SQL Server database, MySQL, LDAP, WMI, etc.). Some query providers and/or their underlying systems impose limitations on the types of queries that they can support.

As an example of things that probably don't translate nice (and would require AsEnumerable or ToArray), imagine a complex expression in the WHERE clause that wouldn't be easy for the query provider to translate.

var happyBirthday = Context.People.Where(x => x.DateOfBirth.Month == DateTime.Now.Month && x.DateOfBirth.Day == DateTime.Now.Day);

Maybe there are some providers that will convert this expression into SQL, but others will refuse it. They won't know how to translate DateTime.Now.Month and DateTime.Now.Day, and they might choke on the .Month and .Day lookups on the DateOfBirth field.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM