Domanda

I am trying to GroupBy a few fields using the following code:

var cars = tmp.Select(a => new { a.Make, a.Model, a.Year });

cars = cars.Distinct()
           .OrderBy(a => a.Make)
           .ThenBy(a => a.Model);

var groupedCars = cars.GroupBy(a => new { a.Make, a.Model })
                      .Select(b => new { b.Make, b.Model, b.Year });

Unfortunately, the very last line of code is giving me errors as is does not recognize the three fields.

'System.Linq.IGrouping(AnonymousType#1,AnonymousType#2)' does not contain a definition for 'Make' and no extension method 'Make' accepting a first argument of type 'System.Linq.IGrouping(AnonymousType#1,AnonymousType#2)' could be found (are you missing a using directive or an assembly reference?)

It is the same error for all three fields (Make, Model, Year).

Any ideas how to fix this?

È stato utile?

Soluzione

Once you've grouped the cars by make and model, each element of the sequence is a group. You can get the key for the group with the Key property, so you can find the group's Make and Model, but Year makes no sense... there will be multiple cars in each group, and they could all have different years. You can use the information within the group, of course. For example:

var groupedCars = cars.GroupBy(a => new { a.Make, a.Model })
                      .Select(g => new { g.Key.Make, g.Key.Model,
                                         MinYear = g.Min(car => car.Year),
                                         MaxYear = g.Max(car => car.Year) });

But fundamentally you need to be thinking about the fact that each element of the sequence is a group, not a single car.

Altri suggerimenti

I am not going to argue with Skeet's logic for my answer is similar.

But my suggestion is to remove the Select projection which does the result selector that sums up the years. That can be done by using the GroupBy overload which does the same process.

cars.GroupBy (car => new { car.Make, car.Model }, // Key selector for make and model as keys
              vehicle => vehicle,                 // Element selector, we want all items of the original car instance which has the year
              (key, vehicle) => new               // Result selector, we want to sum up the min/max year of vehicle.
                                {
                                    Make  = key.Make,
                                    Model = key.Model,
                                    MinYear = vehicle.Min (car => car.Year),
                                    MaxYear = vehicle.Max (car => car.Year)
                                }
              );

Result looks like this:

enter image description here

on this data:

var cars = new List<Car>
{
    new Car() { Make="Dodge", Model="Charger", Year=2007},
    new Car() { Make="BMW",   Model="M6",      Year=2007},
    new Car() { Make="Dodge", Model="Charger", Year=2012},
    new Car() { Make="BMW",   Model="X1",      Year=2013},
    new Car() { Make="BMW",   Model="X1",      Year=2014},
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top