4.0 第十一章 Linq

数据来源
public class Team
    {
        public Team(string name, params int[] years)
        {
            this.Name = name;
            this.Years = years;
        }
        public string Name { get; private set; }
        public int[] Years { get; private set; }

      
    }
     public class Racer 
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Wins { get; set; }
        public string Country { get; set; }
        public int Starts { get; set; }
        public string[] Cars { get; set; }
        public int[] Years { get; set; }
        
        public override string ToString()
        {
            return string.Format("{0} {1}", FirstName, LastName);
        }

      

        public int CompareTo(Racer other)
        {
            return this.LastName.CompareTo(other.LastName);
        }
    }


    public class Formula1
    {
        private static List<Team> teams;
        public static IList<Team> GetContructorChampions()
        {
            if (teams == null)
            {
                teams = new List<Team>()
                {
                    new Team("Vanwall",1958),
                    new Team("Cooper",1959,1960),
                    new Team("Ferrari",1961,1964,1975,1976)
                };
            }
            return teams;
        }
        public static IList<Racer> GetChampions()
        {
            List<Racer> racers = new List<Racer>(40);
        
            racers.Add(new Racer() { FirstName = "Nino", LastName = "Farina", Country = "Italy", Starts = 33, Wins = 5, Years = new int[] { 1950 }, Cars = new string[] { "Alfa Romeo" } });
            racers.Add(new Racer() { FirstName = "Alberto", LastName = "Ascari", Country = "Italy", Starts = 32, Wins = 10, Years = new int[] { 1952, 1953 }, Cars = new string[] { "Ferrari" } });
            racers.Add(new Racer() { FirstName = "Juan Manuel", LastName = "Fangio", Country = "Argentina", Starts = 51, Wins = 24, Years = new int[] { 1951, 1954, 1955, 1956, 1957 }, Cars = new string[] { "Alfa Romeo", "Maserati", "Mercedes", "Ferrari" } });
            racers.Add(new Racer() { FirstName = "Mike", LastName = "Hawthorn", Country = "UK", Starts = 45, Wins = 3, Years = new int[] { 1958 }, Cars = new string[] { "Ferrari" } });
            racers.Add(new Racer() { FirstName = "Phil", LastName = "Hill", Country = "USA", Starts = 48, Wins = 3, Years = new int[] { 1961 }, Cars = new string[] { "Ferrari" } });
            racers.Add(new Racer() { FirstName = "John", LastName = "Surtees", Country = "UK", Starts = 111, Wins = 6, Years = new int[] { 1964 }, Cars = new string[] { "Ferrari" } });
            racers.Add(new Racer() { FirstName = "Jim", LastName = "Clark", Country = "UK", Starts = 72, Wins = 25, Years = new int[] { 1963, 1965 }, Cars = new string[] { "Lotus" } });
            racers.Add(new Racer() { FirstName = "Jack", LastName = "Brabham", Country = "Australia", Starts = 125, Wins = 14, Years = new int[] { 1959, 1960, 1966 }, Cars = new string[] { "Cooper", "Brabham" } });
            racers.Add(new Racer() { FirstName = "Denny", LastName = "Hulme", Country = "New Zealand", Starts = 112, Wins = 8, Years = new int[] { 1967 }, Cars = new string[] { "Brabham" } });
            racers.Add(new Racer() { FirstName = "Graham", LastName = "Hill", Country = "UK", Starts = 176, Wins = 14, Years = new int[] { 1962, 1968 }, Cars = new string[] { "BRM", "Lotus" } });
            racers.Add(new Racer() { FirstName = "Jochen", LastName = "Rindt", Country = "Austria", Starts = 60, Wins = 6, Years = new int[] { 1970 }, Cars = new string[] { "Lotus" } });
            racers.Add(new Racer() { FirstName = "Jackie", LastName = "Stewart", Country = "UK", Starts = 99, Wins = 27, Years = new int[] { 1969, 1971, 1973 }, Cars = new string[] { "Matra", "Tyrrell" } });
            racers.Add(new Racer() { FirstName = "Emerson", LastName = "Fittipaldi", Country = "Brazil", Starts = 143, Wins = 14, Years = new int[] { 1972, 1974 }, Cars = new string[] { "Lotus", "McLaren" } });
            racers.Add(new Racer() { FirstName = "James", LastName = "Hunt", Country = "UK", Starts = 91, Wins = 10, Years = new int[] { 1976 }, Cars = new string[] { "McLaren" } });
            racers.Add(new Racer() { FirstName = "Mario", LastName = "Andretti", Country = "USA", Starts = 128, Wins = 12, Years = new int[] { 1978 }, Cars = new string[] { "Lotus" } });
            racers.Add(new Racer() { FirstName = "Jody", LastName = "Scheckter", Country = "South Africa", Starts = 112, Wins = 10, Years = new int[] { 1979 }, Cars = new string[] { "Ferrari" } });
            racers.Add(new Racer() { FirstName = "Alan", LastName = "Jones", Country = "Australia", Starts = 115, Wins = 12, Years = new int[] { 1980 }, Cars = new string[] { "Williams" } });
            racers.Add(new Racer() { FirstName = "Keke", LastName = "Rosberg", Country = "Finland", Starts = 114, Wins = 5, Years = new int[] { 1982 }, Cars = new string[] { "Williams" } });
            racers.Add(new Racer() { FirstName = "Niki", LastName = "Lauda", Country = "Austria", Starts = 173, Wins = 25, Years = new int[] { 1975, 1977, 1984 }, Cars = new string[] { "Ferrari", "McLaren" } });
            racers.Add(new Racer() { FirstName = "Nelson", LastName = "Piquet", Country = "Brazil", Starts = 204, Wins = 23, Years = new int[] { 1981, 1983, 1987 }, Cars = new string[] { "Brabham", "Williams" } });
            racers.Add(new Racer() { FirstName = "Ayrton", LastName = "Senna", Country = "Brazil", Starts = 161, Wins = 41, Years = new int[] { 1988, 1990, 1991 }, Cars = new string[] { "McLaren" } });
            racers.Add(new Racer() { FirstName = "Nigel", LastName = "Mansell", Country = "UK", Starts = 187, Wins = 31, Years = new int[] { 1992 }, Cars = new string[] { "Williams" } });
            racers.Add(new Racer() { FirstName = "Alain", LastName = "Prost", Country = "France", Starts = 197, Wins = 51, Years = new int[] { 1985, 1986, 1989, 1993 }, Cars = new string[] { "McLaren", "Williams" } });
            racers.Add(new Racer() { FirstName = "Damon", LastName = "Hill", Country = "UK", Starts = 114, Wins = 22, Years = new int[] { 1996 }, Cars = new string[] { "Williams" } });
            racers.Add(new Racer() { FirstName = "Jacques", LastName = "Villeneuve", Country = "Canada", Starts = 165, Wins = 11, Years = new int[] { 1997 }, Cars = new string[] { "Williams" } });
            racers.Add(new Racer() { FirstName = "Mika", LastName = "Hakkinen", Country = "Finland", Starts = 160, Wins = 20, Years = new int[] { 1998, 1999 }, Cars = new string[] { "McLaren" } });
            racers.Add(new Racer() { FirstName = "Michael", LastName = "Schumacher", Country = "Germany", Starts = 250, Wins = 91, Years = new int[] { 1994, 1995, 2000, 2001, 2002, 2003, 2004 }, Cars = new string[] { "Benetton", "Ferrari" } });
            racers.Add(new Racer() { FirstName = "Fernando", LastName = "Alonso", Country = "Spain", Starts = 105, Wins = 19, Years = new int[] { 2005, 2006 }, Cars = new string[] { "Renault" } });
            racers.Add(new Racer() { FirstName = "Kimi", LastName = "Räikkönen", Country = "Finland", Starts = 122, Wins = 15, Years = new int[] { 2007 }, Cars = new string[] { "Ferrari" } });
            return racers;
        }

    }

一、扩展方法
1)Linq中存在大量的扩展方法。在System.Linq命名空间中,存在两个使用极其广泛的类Enumerable和Queryable,它们中就含有许许多多的扩展方法。扩展方法最重要的用途之一就是在Linq中的大量使用。
现在可以使用Enumerable类中的扩展方法Where(),OrderByDescending()和Select()。这些方法都返回IEnumerable<TSource>。
 var champions = new List<Racer>(Formula1.GetChampions());
            IEnumerable<Racer> brazilChampions = champions.Where(r => r.Country == "Brazil").OrderByDescending(r => r.Wins).Select(r => r);

            foreach (Racer r in brazilChampions)
            {
                Console.WriteLine(r);
            }

2)推迟查询的执行
在运行期间定义表达式时,查询就不会执行,查询会在迭代数据项时运行。
扩展方法where。它使用Yield return语句返回谓词为true的元素。
调用ToArray(),ToList()等可以改变这个操作

            var names = new List<string> { "A", "B" };

            var getnames = from n in names
                           orderby n
                           select n;
            foreach (string r in names)
            {
                Console.WriteLine(r);
            }

            names.Add("C");
            foreach (string r in getnames)
            {
                Console.WriteLine(r);
            }
返回结果
A
B
A
B
C
var names = new List<string> { "A", "B" };

            var getnames = (from n in names
                           orderby n
                           select n).ToList();
            foreach (string r in names)
            {
                Console.WriteLine(r);
            }

            names.Add("C");
            foreach (string r in getnames)
            {
                Console.WriteLine(r);
            }
返回结果
A
B
A
B

3)筛选
并不是所有的查询都可以用Linq查询完成。也不是所有的扩展方法都映射到Linq查询子句上。高级查询需要使用扩展方法。
例如在Where()方法中,可以传递第二个参数——索引。
  var Champions = Formula1.GetChampions().Where((r, index) => r.LastName.StartsWith("A") && index % 2 != 0);

            foreach (var r in Champions)
            {
                Console.WriteLine(r);
            }


3)复合的from子句
如果需要根据对象的一个成员进行筛选,而该成员本身是一个系列,就可以使用复合的From子句。(对应的扩展方法是SelectMany)
var Champions = from r in Formula1.GetChampions()
                            from c in r.Cars
                            where c == "Ferrari"
                            select r.LastName;
扩展方法:
var FerrariRacers = Formula1.GetChampions().SelectMany(r => r.Cars, (r, c) => new { Racer = r, Car = c }).Where(r => r.Car == "Ferrari").Select(r => r.Racer.LastName);

4)分组
要根据一个关键字值对查询结果分组,可以使用group子句。
下列中子句group r by r.Country into g根据country信息组合所有赛车手,并定义一个新标识g,它用于访问以后的信息。select子句创建一个带Country和Count属性的匿名类型
var country = from r in Formula1.GetChampions()
                          group r by r.Country into g
                          orderby g.Count() descending, g.Key
                          where g.Count() > 2
                          select new { country = g.Key, count = g.Count() };
扩展方法:
扩展方法GroupBy方法的声明中,它返回实现了IGrouping接口的枚举对象。IGrouping接口定义了Key属性。所以在定义了对这个方法的调用后,可以访问分组关键字。
 var countries = Formula1.GetChampions().GroupBy(r => r.Country).OrderByDescending(g => g.Count()).ThenBy(g => g.Key).Where
                (g => g.Count()>= 2).Select(g => new { country = g.Key, count = g.Count() });

4)对嵌套的对象分组
如果分组的对象应包含嵌套的序列,就可以改变select子句创建的匿名类型。
例子中用一个赋予Racers属性的From/in内部子句指定,内部的from子句使用分组标识符g获得该分组中的所有赛车手。
  var countries2 = from r in Formula1.GetChampions()
                             group r by r.Country into g
                             orderby g.Count() descending, g.Key
                             where g.Count() >= 2
                             select new { country=g.Key,
                             count=g.Count(),
                             Racers=from r1 in g orderby r1.LastName select r1.LastName};

            foreach (var r in countries2)
            {
                Console.WriteLine("Country&&Count: "+r.country+" "+r.count);
                foreach (var name in r.Racers)
                {
                    Console.WriteLine(name);
                }
            }

5)内连接

6)左连接
左连接用join子句和DefaultIfEmpty方法定义,如果没有匹配的就是用DefaultIfEmpty方法定义其右侧的默认值
  var racerandTeam = from r in
                                   from r1 in Formula1.GetChampions()
                                   from yr in r1.Years
                                   select new { Year = yr, Name = r1.FirstName + " " + r1.LastName }
                               join t in
                                   from t1 in Formula1.GetContructorChampions()
                                   from yt in t1.Years
                                   select new { Year=yt,Name=t1.Name}
                               on
                               r.Year equals t.Year into rt
                               from t in rt.DefaultIfEmpty()
                               orderby r.Year
                               select new
                               {
                                   Year = r.Year,
                                   champion = r.Name,
                                   Constructor = t == null ? "No Constructor" : t.Name
                               };





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值