开发者

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 :

  1. order this according to Year, but I need to:

  2. 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 Explorer


If 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))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜