现在的位置: 首页 > 综合 > 正文

C#中的Linq技术标准操作符大全

2013年08月21日 ⁄ 综合 ⁄ 共 19344字 ⁄ 字号 评论关闭
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections ;
  4. using System.Linq;
  5. using System.Text;
  6. namespace LINQ技术
  7. {
  8.     class LINQ查询操作符
  9.     {
  10.         public static void Main()
  11.         {
  12.             //首先,我们先列出Linq一些常用的操作符
  13.             // Where 与 OfType<Tresult>   Where是条件过滤,可以根据为此,其实就是一个委托,返回一个布尔。根据这个委托来实现过滤
  14.             // OfType<Tresult>是根据类型来过滤,他只返回Tresult类型的元素
  15.             // 11.2.1过滤
  16.             IEnumerable<Person> list1 = GetMyList();
  17.             var query1 = from p in list1 where p.age >= 20 select p;
  18.             Console.WriteLine("-----------------过滤:大于等于20岁的人员-------------");
  19.             PrintMyInfo(query1);
  20.             //下面我们写一个对象查询的版本
  21.             Console.WriteLine("-----------------过滤:大于等于30岁的人员(对象版本)-------------");
  22.             list1 = list1.Where<Person>(par => { return par.age >= 30; }).Select(par => par);
  23.             PrintMyInfo(list1);
  24.             // 11.2.2 用索引来过滤
  25.             //这是一个无法使用LINQ语句来实现的功能,他是Where方法的重载
  26.             //在这个方法中,可以传入第二个参数---索引
  27.             //可以是过滤器返回个数的计数器,可以在表达式中使用这个索引,执行基于索引的计算。
  28.             //public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); 委托重载
  29.             IEnumerable<Person> list2 = GetMyList();
  30.             list2 = list2.Where<Person>((p1, p2) => p1.name.StartsWith("a") && p2 <= 1);
  31.             Console.WriteLine("-------------基于索引过滤:姓名以A开头,只要2名,多了不要-------------");
  32.             PrintMyInfo(list2);
  33.             // 11.2.3 类型过滤
  34.             //假定一个数组包含有整型,与字符型元素,而我们只想过滤出字符型元素。呵呵,这么怪的东西,一般是没有啦
  35.             object[] objs = new object[] { 232, 23, 3232, "aladdin", 332, 32323, "fuck" };
  36.             var query2 = objs.OfType<string>();
  37.             Console.WriteLine("-----------类型过滤,只要string型的元素---------");
  38.             foreach (string s in query2)
  39.             {
  40.                 Console.WriteLine(s);
  41.             }
  42.             // 11.2.4 符合的form子句
  43.             // 如果需要根据对象的一个成员过滤,而该成员本身又是一个系列,就要用到符合子句
  44.             // 下面,我们要先出,所年龄在25以上,并且拥有一输开奔驰的牛B人物(一个人可以有多个车)。。我连个蛋蛋也没有,乃球
  45.             IEnumerable<Person> list3 = GetMyList();
  46.             Console.WriteLine("-----------复合子句,所年龄在25以上,并且拥有一输开奔驰的牛B人物---------");
  47.             var quer3 = from p in list3 from c in p.list where c.name.Equals("奔驰") where p.age >= 25 select (p);
  48.             PrintMyInfo(quer3);
  49.             //下面我们来分析一下select投影方法
  50.             //public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
  51.             //Select<TSource, TResult>方法定义了2个泛型类型,源,返回类型
  52.             //IEnumerable<TResult> 返回可以跌代的类型
  53.             //2个参数 :this IEnumerable<TSource> source 是指本方法要扩展IEnumerable<TSource>类型。
  54.             // Func<TSource, TResult> selector委托
  55.             // 委托的声明: public delegate TResult Func<T, TResult>(T arg)
  56.             IEnumerable<Person> list4 = GetMyList();
  57.             var query4 = list4.Select(p => p.age);
  58.             //Select第一个参数是隐式的,所以我们不用关心,只要明白它是扩展哪个类型就可以了
  59.             //第二个参数通过源类型,返回一个投影类型,可以是源类型的一个字段,也可以将源类型直接返回,也就是我们直接写 select p
  60.             //以上示例,我们是将源类型中的age返回,它是int 型。下面我们跌代,就不可以用Person来跌代了。
  61.             Console.WriteLine("-----------按年纪投影---------");
  62.             foreach (int p in query4)
  63.             {
  64.                 Console.WriteLine(p);
  65.             }
  66.             //在select与where这两个方法上,可能会存在一点误解,我开始认为select可以做与where一样的事情,下面我们证实一下
  67.             var query5 = list4.Select(p =>
  68.             {
  69.                 if (p.age >= 25)
  70.                 {
  71.                     return new Person(p.name, p.age);
  72.                 }
  73.                 else
  74.                 {
  75.                     return new Person("node", 1);
  76.                 }
  77.             });
  78.             //以上代码,我们想用select来过滤超过25岁的人,但是,无法将不需要的部分不要,所以,还是没办法做与where一样的功能
  79.             //而where方法,返回的是bool,可以筛选不合格的条件的。
  80.             Console.WriteLine("-----------select模拟 where ---------");
  81.             foreach (Person p in query5)
  82.             {
  83.                 Console.WriteLine(p.name);
  84.             }
  85.             //看完了select我们接着看SelectMany方法,其实复合查询中,就是用到了这个方法。
  86.             //public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
  87.             //    this IEnumerable<TSource> source,
  88.             //    Func<TSource, IEnumerable<TCollection>> collectionSelector,
  89.             //    Func<TSource, TCollection, TResult> resultSelector
  90.             //)
  91.             //返回IEnumerable<TResult>
  92.             //3个参数,第一个是隐式的,也就是指明他扩展的是哪种类型的this IEnumerable<TSource> source
  93.             //第二个参数,是一个委托 Func<TSource, IEnumerable<TCollection>> collectionSelector,
  94.             //下面我们看这个委托的声明:public delegate TResult Func<T, TResult>( T arg )
  95.             //这里与select方法有一点不同,select用委托做参数时保留了TResult类型,而这里我们指定成了IEnumerable<TCollection>>
  96.             //第三个参数,同样也是一个委托 Func<TSource, TCollection, TResult> resultSelector
  97.             //public delegate TResult Func<T1, T2, TResult>(T1 arg1,T2 arg2)
  98.             IEnumerable<Person> list5 = GetMyList();
  99.             //以下示例是SelectMany方法的第一种重载,只是将一个序列的子集序列查出来
  100.             var query6 = list5.SelectMany(par => par.list).Where(p => p.name.Equals("奔驰"));
  101.             Console.WriteLine("查询序列的序列-------------------");
  102.             foreach (Cars car in query6)
  103.             {
  104.                 Console.WriteLine(car.name);
  105.             }
  106.             //我们用对象方法的方式来查询一次所有25岁以上的拥有奔驰车的牛B人物
  107.             var query7 = list5.SelectMany(cars => cars.list, (per, car) => new { Person = per, Cars = car }).Where(p => p.Person.age >= 25 && p.Cars.name.Equals("奔驰")).Select(par => par.Person.name);
  108.             Console.WriteLine("对象方式复合查询-------------------");
  109.             foreach (var a in query7)
  110.             {
  111.                 Console.WriteLine(a);
  112.             }
  113.             // 11.2.5 排序
  114.             // 下面我们写一个小例,把人按照年纪排一次序
  115.             var query8 = list5.Select(p => p).OrderBy(p => p.age).ThenBy(p => p.name);
  116.             var query9 = list5.Select(p => p).OrderByDescending(p => p.age).Take(2);
  117.             Console.WriteLine("------------升序所有人--------------");
  118.             PrintMyInfo(query8);
  119.             Console.WriteLine("降序所有人--------------------");
  120.             PrintMyInfo(query9);
  121.             // Order 与 OrderByDescending方法都是返回IOrderedEnumerable<TSource>接口类型,这个接口扩展自IEnumerable<T>
  122.             //public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
  123.             //    this IEnumerable<TSource> source,
  124.             //    Func<TSource, TKey> keySelector
  125.             //)
  126.             // 11.2.6 分组
  127.             //下面我们先用linq 语句实现分组查询,我们把人的年纪分组,我们只接受元素大于2个的组,每一组我们个数排,如果个数相同,我们按年纪排。
  128.             var query10 = from per in list5
  129.                           group per by per.age into g
  130.                           orderby g.Count(), g.Key
  131.                           where g.Count() >= 2
  132.                           select new { Age = g.Key, Count = g.Count() };
  133.             Console.WriteLine("--------分组查询-----------");
  134.             foreach (var a in query10)
  135.             {
  136.                 Console.WriteLine(a.Age + "  " + a.Count);
  137.             }
  138.             //方法方式实现上面功能
  139.             var query11 = list5.GroupBy(per => per.age)
  140.                 .OrderBy(p => p.Count()).ThenBy(p => p.Key)
  141.                 .Where(p => p.Count() >= 2)
  142.                 .Select(p => new { Age = p.Key, Count = p.Count() });
  143.             Console.WriteLine("--------分组查询,方法方式-----------");
  144.             foreach (var a in query11)
  145.             {
  146.                 Console.WriteLine(a.Age + "  " + a.Count);
  147.             }
  148.             // 11.2.7 对嵌套的对象分组
  149.             //如上所示,我们将年纪分组,如果想要把组内人员的名字一并返回,势必将名字会当成一个序列,此时,它是一对多的关系
  150.             Console.WriteLine("---------嵌套对象分组-------------");
  151.             var query12 = list5.GroupBy(per => per.age)
  152.                 .OrderBy(p => p.Count()).ThenBy(p => p.Key)
  153.                 .Where(p => p.Count() >= 2)
  154.                 .Select(p => new
  155.                 {
  156.                     Age = p.Key,
  157.                     Count = p.Count(),
  158.                     Persons = from per in p orderby per.name select per
  159.                 });
  160.             foreach (var a in query12)
  161.             {
  162.                 Console.WriteLine(a.Age + "  " + a.Count);
  163.                 foreach (var b in a.Persons)
  164.                 {
  165.                     Console.WriteLine(b.name);
  166.                 }
  167.             }
  168.             // 11.2.8 连接
  169.             //搞不个恰当的例子吧,我们现在扩展一种类,来描述动物,同样具有名字与年纪,我们用连接,查询与动物相同年纪的人
  170.             var query13 = GetMyAnimalList().Select(animal => animal);
  171.             var query14 = GetMyList().Select(person => person);
  172.             var query15 = from per in query14
  173.                           join animal in query13 on per.age equals animal.age
  174.                           select new
  175.                               {
  176.                                   DogName = animal.name,
  177.                                   DogAge = animal.age,
  178.                                   PersonName = per.name,
  179.                                   PersonAge = per.age
  180.                               };
  181.             foreach (var v in query15)
  182.             {
  183.                 Console.WriteLine("人名:{0} , 年纪{1}------动物名:{2} ,年纪{3}", v.PersonName, v.PersonAge, v.DogName, v.DogAge);
  184.             }
  185.             // 11.2.9 设置方法
  186.             //Concat(连接) 
  187.             //说明:连接不同的集合,不会自动过滤相同项;延迟。
  188.             IEnumerable<Animal> ani = GetMyAnimalList();
  189.             IEnumerable<Person> pers = GetMyList();
  190.             int i = 0;
  191.             var query16 = (from a in ani select a.name).Concat(from p in pers select p.name);
  192.             Console.WriteLine("--------------连接操作----------");
  193.             foreach (var str in query16)
  194.             {
  195.                 ++i;
  196.                 Console.WriteLine(str);
  197.             }
  198.             Console.WriteLine("个数:" + i);
  199.             //可以看出,我们将所有人与动物的名字做了一个连接操作,全部显示了出,不过并没有自动过滤重复项目
  200.             //以上示例,只是连接了一个字段,下面我们复合型式连接
  201.             Console.WriteLine("--------------复合连接操作----------");
  202.             var query17 = (from a in ani select new { Name = a.name, Age = a.age })
  203.                           .Concat(from p in pers select new { Name = p.name, Age = p.age });
  204.             i = 0;
  205.             foreach (var str in query17)
  206.             {
  207.                 ++i;
  208.                 Console.WriteLine(str.Name + " " + str.Age);
  209.             }
  210.             Console.WriteLine("个数:" + i);
  211.             //Union(合并) 
  212.             //说明:连接不同的集合,自动过滤相同项;延迟。即是将两个集合进行合并操作,过滤相同的项。
  213.             var query18 = (from a in ani select a.name).Union(from p in pers select p.name);
  214.             Console.WriteLine("--------------合并操作----------");
  215.             i = 0;
  216.             foreach (var str in query18)
  217.             {
  218.                 Console.WriteLine(str);
  219.                 ++i;
  220.             }
  221.             Console.WriteLine("个数:" + i);
  222.             //可以看出,我们将所有人与动物的名字做了一个连接操作,全部显示了出,不过并没有自动过滤重复项目
  223.             //以上示例,只是连接了一个字段,下面我们复合型式连接
  224.             IEnumerable<Animal> ani2 = GetMyAnimalList();
  225.             IEnumerable<Person> pers2 = GetMyList();
  226.             Console.WriteLine("--------------复合合并操作----------");
  227.             var query19 = (from a in ani2 select new { Age = a.age, Name = a.name })
  228.                           .Union(from p in pers2 select new { Age = p.age, Name = p.name });
  229.             i = 0;
  230.             foreach (var str in query19)
  231.             {
  232.                 ++i;
  233.                 Console.WriteLine(str.Age + " " + str.Name);
  234.             }
  235.             Console.WriteLine("个数:" + i);
  236.             //这时有一点疑问,并集比较时,没有按匿名对象,而依然是在用 name,不知道为什么
  237.             // Intersect(相交) 
  238.             //说明:取相交项;延迟。即是获取不同集合的相同项(交集)。即先遍历第一个集合,找出所有唯一的元素,
  239.             //然后遍历第二个集合,并将每个元素与前面找出的元素作对比,返回所有在两个集合内都出现的元素。
  240.             Console.WriteLine("--------------相交操作----------");
  241.             var query20 = (from a in ani2 select new { Age = a.age, Name = a.name })
  242.                           .Intersect(from p in pers2 select new { Age = p.age, Name = p.name });
  243.             i = 0;
  244.             foreach (var str in query20)
  245.             {
  246.                 ++i;
  247.                 Console.WriteLine(str.Age + " " + str.Name);
  248.             }
  249.             Console.WriteLine("个数:" + i);
  250.             //  Except(与非) 
  251.             //说明:排除相交项;延迟。即是从某集合中删除与另一个集合中相同的项。
  252.             //   先遍历第一个集合,找出所有唯一的元素,然后再遍历第二个集合,
  253.             //   返回第二个集合中所有未出现在前面所得元素集合中的元素。
  254.             Console.WriteLine("--------------与非操作----------");
  255.             var query21 = (from a in pers2 select new { Age = a.age, Name = a.name })
  256.                           .Except(from p in ani2 select new { Age = p.age, Name = p.name });
  257.             i = 0;
  258.             foreach (var str in query21)
  259.             {
  260.                 ++i;
  261.                 Console.WriteLine(str.Age + " " + str.Name);
  262.             }
  263.             Console.WriteLine("个数:" + i);
  264.             
  265.             //11.210 分区
  266.             //扩展方法 Take与Skip等分区操作可以用于分页,例如显示5*5个人
  267.             //一页显示的条数
  268.             int pageSize = 2;
  269.             //页数计算
  270.             int numberPages = (int)Math.Ceiling(GetMyList().Count() / (double)pageSize);
  271.             for (int page = 0; page < numberPages; page++)
  272.             {
  273.                 Console.WriteLine("-------------------第{0}页-------------------------------", page);
  274.                 var persons = ( from r in GetMyList() select r.name ).Skip( page * pageSize ).Take( pageSize ) ;
  275.                 foreach( var a in persons )
  276.                 {
  277.                     Console.WriteLine( a ) ;
  278.                 }
  279.             }
  280.             //可以看出skip是指忽略多少条,Take是指从取到的记录中取几条
  281.             //11,2,11合并操作
  282.             //Count用来计算项目数,下面我们选中拥有车超过3辆的人
  283.             var query22 = from person in GetMyList() where person.list.Count() >= 2 select new { Name = person.name , Age = person.age , Count = person.list.Count() } ;
  284.             Console.WriteLine( "-----------------------选出拥有车俩3俩以上的人------------" ) ;
  285.             
  286.             foreach( var a in query22 )
  287.             {
  288.                 Console.WriteLine( a.Name + " " + a.Age + " " + a.Count ) ;
  289.             }
  290.             //Sum汇总数字的合
  291.             //下面,我们用Sum求出所有人年纪的总合(按人名先分组)
  292.             Console.WriteLine( "-------------------------所有人年纪的总合------------------" ) ;
  293.             var query23 = from ppp in GetMyList()
  294.                           group ppp by ppp.name into g
  295.                           select new
  296.                               {
  297.                                   Name = g.Key,
  298.                                   AgeSum = (from p in pers select p.age).Sum(),
  299.                                   Count = g.Count() 
  300.                               };
  301.             foreach (var a in query23)
  302.             {
  303.                 Console.WriteLine(a.Name + "   " + a.AgeSum + "  " + a.Count );
  304.             }
  305.             
  306.             
  307.             //11.2.12转换
  308.             //之前我们用到的查询,都是在foreach时才会真正的执行,下面我们的方式是强制立即执行,将结果放数集合数组等容器中
  309.             List<Person> list = (from p in GetMyList() select p).ToList();
  310.             Console.WriteLine("立即执行查询-----------------------");
  311.             foreach (var a in list)
  312.             {
  313.                 Console.WriteLine(a.age + a.name ) ;
  314.                 foreach( var p in a.list )
  315.                 {
  316.                     Console.WriteLine( p.name ) ;
  317.                 }
  318.             }
  319.             //接着,我们做一个字典,车对人(一对多)
  320.             ILookup<string, Person> per111 = (from per in GetMyList()
  321.                                                from c in per.list
  322.                                                select new
  323.                                                    {
  324.                                                        Car = c.name,
  325.                                                        Person = per
  326.                                                    }).ToLookup(p => p.Car, p => p.Person);
  327.             Console.WriteLine( per111.Count ) ;
  328.             if ( per111.Contains("奔驰") )
  329.             { 
  330.                 foreach( var p in per111["奔驰"] )
  331.                 {
  332.                     Console.WriteLine( "有这个车的人:{0}" , p.name ) ;
  333.                 }
  334.             }
  335.             //如果要在非泛型版的集合上使用,可以用Cast方法强制得到类型
  336.             ArrayList arr = new ArrayList( GetMyList() as ICollection ) ;
  337.             var qqq = from a in arr.Cast<Person>()  where a.name == "aladdin" select a ;
  338.             //11.2.13生成操作符
  339.             // Range() Empty() Repear()不是扩展方法,而是返回序列的正常静态方法
  340.             // 在LINQ to Objects中,这些方法可以用于Enumearable类
  341.             // 有时需要填充一个范围的数字,这时需要用到Range方法,第一个参数做为起始值,第二个是指填充的项目数
  342.             var values = Enumerable.Range( 1 ,20 ).Select( n => n*3 ) ;
  343.             foreach( var a in values )
  344.             {
  345.                 Console.Write( a + " " ) ;
  346.             }
  347.             //结果1 2 3 4 .....20
  348.             //比如某个方法,参数是一个集合,我们传一个空进去,就可以用Empty
  349.             var em = Enumerable.Empty<int>() ;
  350.             var pep = Enumerable.Repeat( "fuck " , 10 ) ;
  351.             foreach( var a in pep )
  352.             {
  353.                 Console.WriteLine( a ) ;
  354.             }
  355.             //Repeat用于把特定元素按指定的重复次数爹代
  356.             Console.ReadLine();
  357.         }
  358.         public static void PrintMyInfo(IEnumerable<Person> en)
  359.         {
  360.             foreach (Person per in en)
  361.             {
  362.                 Console.WriteLine("姓名:{0} 年龄:{1}", per.name, per.age);
  363.             }
  364.         }
  365.         public static IEnumerable<Animal> GetMyAnimalList()
  366.         {
  367.             List<Animal> lists = new List<Animal>();
  368.             Animal p1 = new Animal("aladdin", 21);
  369.             Animal p2 = new Animal("apple", 22);
  370.             Animal p3 = new Animal("angel", 30);
  371.             Animal p4 = new Animal("jacky", 22);
  372.             lists.Add(p1);
  373.             lists.Add(p2);
  374.             lists.Add(p3);
  375.             lists.Add(p4);
  376.             return lists;
  377.         }
  378.         public static IEnumerable<Person> GetMyList()
  379.         {
  380.             List<Person> lists = new List<Person>();
  381.             Person p1 = new Person("aladdin", 21);
  382.             Person p2 = new Person("apple", 22);
  383.             Person p3 = new Person("angel", 30);
  384.             Person p4 = new Person("jacky", 20);
  385.             Person p5 = new Person("zhao", 11);
  386.             Person p6 = new Person("fuck", 33);
  387.             Person p7 = new Person("emep", 25);
  388.             Person p8 = new Person("xiaoming", 88);
  389.             Person p9 = new Person("along", 88);
  390.             Person p10 = new Person("dafei", 99);
  391.             Person p11 = new Person("bige", 99);
  392.             Person p12 = new Person("feitianlong", 77);
  393.             Person p13 = new Person("dalianmao", 77);
  394.             Person p14 = new Person("guixianren", 21);
  395.             Person p15 = new Person("yuebuqun", 21);
  396.             p1.list.Add(new Cars("奔驰"));
  397.             p1.list.Add(new Cars("宝马"));
  398.             p1.list.Add(new Cars("拖拉机"));
  399.             p2.list.Add(new Cars("自行车"));
  400.             p2.list.Add(new Cars("摩托"));
  401.             p3.list.Add(new Cars("奔驰"));
  402.             p3.list.Add(new Cars("陆虎"));
  403.             p4.list.Add(new Cars("捷达"));
  404.             p4.list.Add(new Cars("哈飞"));
  405.             p5.list.Add(new Cars("奔驰"));
  406.             p5.list.Add(new Cars("宝时捷"));
  407.             p6.list.Add(new Cars("奔驰"));
  408.             p6.list.Add(new Cars("霸道"));
  409.             p7.list.Add(new Cars("昌河"));
  410.             p7.list.Add(new Cars("长安之星"));
  411.             lists.Add(p1);
  412.             lists.Add(p2);
  413.             lists.Add(p3);
  414.             lists.Add(p4);
  415.             lists.Add(p5);
  416.             lists.Add(p6);
  417.             lists.Add(p7);
  418.             lists.Add(p8);
  419.             lists.Add(p9);
  420.             lists.Add(p10);
  421.             lists.Add(p11);
  422.             lists.Add(p12);
  423.             lists.Add(p13);
  424.             lists.Add(p14);
  425.             lists.Add(p15);
  426.             return lists;
  427.         }
  428.     }
  429.     class Person
  430.     {
  431.         public string name;
  432.         public int age;
  433.         public List<Cars> list = new List<Cars>();
  434.         public Person(string name, int age)
  435.         {
  436.             this.name = name;
  437.             this.age = age;
  438.         }
  439.     }
  440.     class Cars
  441.     {
  442.         public string name;
  443.         public Cars(string name)
  444.         {
  445.             this.name = name;
  446.         }
  447.     }
  448.     class Animal
  449.     {
  450.         public string name;
  451.         public int age;
  452.         public Animal(string name, int age)
  453.         {
  454.             this.name = name;
  455.             this.age = age;
  456.         }
  457.     }
  458. }

抱歉!评论已关闭.