C# LINQ calculated Group By
To take it down to brass tacks, I have a List containing 100 various records. A Car has a Year, Make and Model.
I need to be able to :
order this according to Year, but I need to:
have all Cars that are Ford Explorers appear as a "group" at the end of my List (also ordered according to Year)
I'm not sure if I'll have to create 2 separate Lis开发者_开发问答t and then merge them... seems like there should be a better way to do this than having to create multiple objects.
Your help is appreciated and welcomed!
Many Thanks, paul
Example:
2001 Hummer H1 2002 Ford Focus 2008 BMW 325i 2008 Ford Escape 2009 BMW 328i 2009 Mitsubishi Galant 2003 Ford Explorer 2004 Ford Explorer 2008 Ford Explorer 2009 Ford ExplorerIf you truly only want the Ford Explorers to be grouped, you can do the following:
var groupedByFordExplorer = from c in cars
let isFordExplorer = c.Make == "Ford" && c.Model == "Explorer"
orderby isFordExplorer, c.Year
select c;
What the above query does is create an inline value , isFordExplorer
, and assigns it a boolean value using the let
keyword indicating whether the car is a Ford Explorer. That value can then be sorted by, along with the Year. The following is a working program that should demonstrate the concept:
class Program
{
static void Main(string[] args)
{
var cars = new List<Car>
{
new Car { Year = 2009, Make = "Ford", Model = "Explorer" },
new Car { Year = 2001, Make = "Hummer", Model = "H1" },
new Car { Year = 2002, Make = "Ford", Model = "Focus" },
new Car { Year = 2008, Make = "BMW", Model = "325i" },
new Car { Year = 2008, Make = "Ford", Model = "Explorer" },
new Car { Year = 2008, Make = "Ford", Model = "Escape" },
new Car { Year = 2009, Make = "Mitsubishi", Model = "Galant" },
new Car { Year = 2004, Make = "Ford", Model = "Explorer" },
new Car { Year = 2009, Make = "BMW", Model = "329i" },
new Car { Year = 2003, Make = "Ford", Model = "Explorer" }
};
var groupedByFordExplorer = from c in cars
let isFordExplorer = c.Make == "Ford" && c.Model == "Explorer"
orderby isFordExplorer, c.Year
select c;
foreach (var car in groupedByFordExplorer)
{
Console.WriteLine("{0} {1} {2}", car.Year, car.Make, car.Model);
}
Console.ReadLine();
}
}
class Car
{
public int Year { get; set; }
public string Make { get; set; }
public string Model { get; set; }
}
This should do it:
var query = list.OrderBy(car => car.Make == "Ford" && car.Model == "Explorer")
.ThenBy(car => car.Year);
(Obviously adjust the test for Ford Explorer-ness.)
Basically think of Ford Explorer-ness as a Boolean property, where false is ordered before true. You can express this as a query expression too, of course:
var query = from car in list
orderby car.Make == "Ford" && car.Model == "Explorer", car.Year
select car;
(I tend to prefer dot notation in this case.)
cars.OrderBy(c =>
(c.Make == "Ford" && c.Model == "Explorer")
? c.Year + 10000
: c.Year)
.ToList()
thinking about my comment below, if it were LINQ to sql, I would probably write it with a union:
cars.Where(c => c.Make != "Ford" || c.Model != "Explorer")
.OrderBy(c => c.Year)
.Union(cars.Where(c => c.Make == "Ford" && c.Model == "Explorer")
.OrderBy(c => c.Year))
精彩评论