• C# 中的 Linq 操作符


    using System; 
    using System.Collections.Generic; 
    using System.Collections ; 
    using System.Linq; 
    using System.Text; 
    
    namespace LINQ技术 
    { 
        class LINQ查询操作符 
        { 
            public static void Main() 
            { 
                //首先,我们先列出Linq一些常用的操作符 
                // Where 与 OfType<Tresult>   Where是条件过滤,可以根据为此,其实就是一个委托,返回一个布尔。根据这个委托来实现过滤 
                // OfType<Tresult>是根据类型来过滤,他只返回Tresult类型的元素 
    
                // 11.2.1过滤 
                IEnumerable<Person> list1 = GetMyList(); 
                var query1 = from p in list1 where p.age >= 20 select p; 
                Console.WriteLine("-----------------过滤:大于等于20岁的人员-------------"); 
                PrintMyInfo(query1); 
                //下面我们写一个对象查询的版本 
                Console.WriteLine("-----------------过滤:大于等于30岁的人员(对象版本)-------------"); 
                list1 = list1.Where<Person>(par => { return par.age >= 30; }).Select(par => par); 
                PrintMyInfo(list1); 
    
    
                // 11.2.2 用索引来过滤 
                //这是一个无法使用LINQ语句来实现的功能,他是Where方法的重载 
                //在这个方法中,可以传入第二个参数---索引 
                //可以是过滤器返回个数的计数器,可以在表达式中使用这个索引,执行基于索引的计算。 
                //public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); 委托重载 
                IEnumerable<Person> list2 = GetMyList(); 
                list2 = list2.Where<Person>((p1, p2) => p1.name.StartsWith("a") && p2 <= 1); 
                Console.WriteLine("-------------基于索引过滤:姓名以A开头,只要2名,多了不要-------------"); 
                PrintMyInfo(list2); 
    
                // 11.2.3 类型过滤 
                //假定一个数组包含有整型,与字符型元素,而我们只想过滤出字符型元素。呵呵,这么怪的东西,一般是没有啦 
                object[] objs = new object[] { 232, 23, 3232, "aladdin", 332, 32323, "fuck" }; 
                var query2 = objs.OfType<string>(); 
                Console.WriteLine("-----------类型过滤,只要string型的元素---------"); 
    
                foreach (string s in query2) 
                { 
                    Console.WriteLine(s); 
                } 
    
                // 11.2.4 符合的form子句 
                // 如果需要根据对象的一个成员过滤,而该成员本身又是一个系列,就要用到符合子句 
                // 下面,我们要先出,所年龄在25以上,并且拥有一输开奔驰的牛B人物(一个人可以有多个车)。。我连个蛋蛋也没有,乃球 
                IEnumerable<Person> list3 = GetMyList(); 
                Console.WriteLine("-----------复合子句,所年龄在25以上,并且拥有一输开奔驰的牛B人物---------"); 
                var quer3 = from p in list3 from c in p.list where c.name.Equals("奔驰") where p.age >= 25 select (p); 
                PrintMyInfo(quer3); 
    
                //下面我们来分析一下select投影方法 
                //public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) 
                //Select<TSource, TResult>方法定义了2个泛型类型,源,返回类型 
                //IEnumerable<TResult> 返回可以跌代的类型 
                //2个参数 :this IEnumerable<TSource> source 是指本方法要扩展IEnumerable<TSource>类型。 
                // Func<TSource, TResult> selector委托 
                // 委托的声明: public delegate TResult Func<T, TResult>(T arg) 
                IEnumerable<Person> list4 = GetMyList(); 
                var query4 = list4.Select(p => p.age); 
                //Select第一个参数是隐式的,所以我们不用关心,只要明白它是扩展哪个类型就可以了 
                //第二个参数通过源类型,返回一个投影类型,可以是源类型的一个字段,也可以将源类型直接返回,也就是我们直接写 select p 
                //以上示例,我们是将源类型中的age返回,它是int 型。下面我们跌代,就不可以用Person来跌代了。 
                Console.WriteLine("-----------按年纪投影---------"); 
                foreach (int p in query4) 
                { 
                    Console.WriteLine(p); 
                } 
                //在select与where这两个方法上,可能会存在一点误解,我开始认为select可以做与where一样的事情,下面我们证实一下 
                var query5 = list4.Select(p => 
                { 
    
                    if (p.age >= 25) 
                    { 
                        return new Person(p.name, p.age); 
                    } 
                    else 
                    { 
                        return new Person("node", 1); 
                    } 
                }); 
    
                //以上代码,我们想用select来过滤超过25岁的人,但是,无法将不需要的部分不要,所以,还是没办法做与where一样的功能 
                //而where方法,返回的是bool,可以筛选不合格的条件的。 
                Console.WriteLine("-----------select模拟 where ---------"); 
                foreach (Person p in query5) 
                { 
                    Console.WriteLine(p.name); 
                } 
    
                //看完了select我们接着看SelectMany方法,其实复合查询中,就是用到了这个方法。 
                //public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>( 
                //    this IEnumerable<TSource> source, 
                //    Func<TSource, IEnumerable<TCollection>> collectionSelector, 
                //    Func<TSource, TCollection, TResult> resultSelector 
                //) 
                //返回IEnumerable<TResult> 
                //3个参数,第一个是隐式的,也就是指明他扩展的是哪种类型的this IEnumerable<TSource> source 
                //第二个参数,是一个委托 Func<TSource, IEnumerable<TCollection>> collectionSelector, 
                //下面我们看这个委托的声明:public delegate TResult Func<T, TResult>( T arg ) 
                //这里与select方法有一点不同,select用委托做参数时保留了TResult类型,而这里我们指定成了IEnumerable<TCollection>> 
                //第三个参数,同样也是一个委托 Func<TSource, TCollection, TResult> resultSelector 
                //public delegate TResult Func<T1, T2, TResult>(T1 arg1,T2 arg2) 
    
                IEnumerable<Person> list5 = GetMyList(); 
                //以下示例是SelectMany方法的第一种重载,只是将一个序列的子集序列查出来 
                var query6 = list5.SelectMany(par => par.list).Where(p => p.name.Equals("奔驰")); 
                Console.WriteLine("查询序列的序列-------------------"); 
    
                foreach (Cars car in query6) 
                { 
                    Console.WriteLine(car.name); 
                } 
    
                //我们用对象方法的方式来查询一次所有25岁以上的拥有奔驰车的牛B人物 
                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); 
                Console.WriteLine("对象方式复合查询-------------------"); 
                foreach (var a in query7) 
                { 
                    Console.WriteLine(a); 
                } 
    
                // 11.2.5 排序 
                // 下面我们写一个小例,把人按照年纪排一次序 
                var query8 = list5.Select(p => p).OrderBy(p => p.age).ThenBy(p => p.name); 
                var query9 = list5.Select(p => p).OrderByDescending(p => p.age).Take(2); 
                Console.WriteLine("------------升序所有人--------------"); 
                PrintMyInfo(query8); 
                Console.WriteLine("降序所有人--------------------"); 
                PrintMyInfo(query9); 
                // Order 与 OrderByDescending方法都是返回IOrderedEnumerable<TSource>接口类型,这个接口扩展自IEnumerable<T> 
                //public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>( 
                //    this IEnumerable<TSource> source, 
                //    Func<TSource, TKey> keySelector 
                //) 
    
                // 11.2.6 分组 
                //下面我们先用linq 语句实现分组查询,我们把人的年纪分组,我们只接受元素大于2个的组,每一组我们个数排,如果个数相同,我们按年纪排。 
                var query10 = from per in list5 
                              group per by per.age into g 
                              orderby g.Count(), g.Key 
                              where g.Count() >= 2 
                              select new { Age = g.Key, Count = g.Count() }; 
    
                Console.WriteLine("--------分组查询-----------"); 
                foreach (var a in query10) 
                { 
                    Console.WriteLine(a.Age + "  " + a.Count); 
                } 
                //方法方式实现上面功能 
    
                var query11 = list5.GroupBy(per => per.age) 
                    .OrderBy(p => p.Count()).ThenBy(p => p.Key) 
                    .Where(p => p.Count() >= 2) 
                    .Select(p => new { Age = p.Key, Count = p.Count() }); 
    
                Console.WriteLine("--------分组查询,方法方式-----------"); 
                foreach (var a in query11) 
                { 
                    Console.WriteLine(a.Age + "  " + a.Count); 
                } 
    
    
                // 11.2.7 对嵌套的对象分组 
                //如上所示,我们将年纪分组,如果想要把组内人员的名字一并返回,势必将名字会当成一个序列,此时,它是一对多的关系 
    
                Console.WriteLine("---------嵌套对象分组-------------"); 
                var query12 = list5.GroupBy(per => per.age) 
                    .OrderBy(p => p.Count()).ThenBy(p => p.Key) 
                    .Where(p => p.Count() >= 2) 
                    .Select(p => new 
                    { 
                        Age = p.Key, 
                        Count = p.Count(), 
                        Persons = from per in p orderby per.name select per 
                    }); 
                foreach (var a in query12) 
                { 
                    Console.WriteLine(a.Age + "  " + a.Count); 
                    foreach (var b in a.Persons) 
                    { 
                        Console.WriteLine(b.name); 
                    } 
                } 
    
                // 11.2.8 连接 
                //搞不个恰当的例子吧,我们现在扩展一种类,来描述动物,同样具有名字与年纪,我们用连接,查询与动物相同年纪的人 
                var query13 = GetMyAnimalList().Select(animal => animal); 
                var query14 = GetMyList().Select(person => person); 
                var query15 = from per in query14 
                              join animal in query13 on per.age equals animal.age 
                              select new 
                                  { 
                                      DogName = animal.name, 
                                      DogAge = animal.age, 
                                      PersonName = per.name, 
                                      PersonAge = per.age 
                                  }; 
    
                foreach (var v in query15) 
                { 
                    Console.WriteLine("人名:{0} , 年纪{1}------动物名:{2} ,年纪{3}", v.PersonName, v.PersonAge, v.DogName, v.DogAge); 
                } 
    
    
                // 11.2.9 设置方法 
                //Concat(连接)  
                //说明:连接不同的集合,不会自动过滤相同项;延迟。 
                IEnumerable<Animal> ani = GetMyAnimalList(); 
                IEnumerable<Person> pers = GetMyList(); 
                int i = 0; 
                var query16 = (from a in ani select a.name).Concat(from p in pers select p.name); 
                Console.WriteLine("--------------连接操作----------"); 
                foreach (var str in query16) 
                { 
                    ++i; 
                    Console.WriteLine(str); 
                } 
    
                Console.WriteLine("个数:" + i); 
                //可以看出,我们将所有人与动物的名字做了一个连接操作,全部显示了出,不过并没有自动过滤重复项目 
    
                //以上示例,只是连接了一个字段,下面我们复合型式连接 
                Console.WriteLine("--------------复合连接操作----------"); 
                var query17 = (from a in ani select new { Name = a.name, Age = a.age }) 
                              .Concat(from p in pers select new { Name = p.name, Age = p.age }); 
    
                i = 0; 
                foreach (var str in query17) 
                { 
                    ++i; 
                    Console.WriteLine(str.Name + " " + str.Age); 
                } 
                Console.WriteLine("个数:" + i); 
                //Union(合并)  
                //说明:连接不同的集合,自动过滤相同项;延迟。即是将两个集合进行合并操作,过滤相同的项。 
    
                var query18 = (from a in ani select a.name).Union(from p in pers select p.name); 
                Console.WriteLine("--------------合并操作----------"); 
                i = 0; 
                foreach (var str in query18) 
                { 
                    Console.WriteLine(str); 
                    ++i; 
                } 
                Console.WriteLine("个数:" + i); 
                //可以看出,我们将所有人与动物的名字做了一个连接操作,全部显示了出,不过并没有自动过滤重复项目 
    
                //以上示例,只是连接了一个字段,下面我们复合型式连接 
                IEnumerable<Animal> ani2 = GetMyAnimalList(); 
                IEnumerable<Person> pers2 = GetMyList(); 
    
                Console.WriteLine("--------------复合合并操作----------"); 
                var query19 = (from a in ani2 select new { Age = a.age, Name = a.name }) 
                              .Union(from p in pers2 select new { Age = p.age, Name = p.name }); 
    
                i = 0; 
                foreach (var str in query19) 
                { 
                    ++i; 
                    Console.WriteLine(str.Age + " " + str.Name); 
                } 
                Console.WriteLine("个数:" + i); 
                //这时有一点疑问,并集比较时,没有按匿名对象,而依然是在用 name,不知道为什么 
    
    
                // Intersect(相交)  
                //说明:取相交项;延迟。即是获取不同集合的相同项(交集)。即先遍历第一个集合,找出所有唯一的元素, 
                //然后遍历第二个集合,并将每个元素与前面找出的元素作对比,返回所有在两个集合内都出现的元素。 
                Console.WriteLine("--------------相交操作----------"); 
                var query20 = (from a in ani2 select new { Age = a.age, Name = a.name }) 
                              .Intersect(from p in pers2 select new { Age = p.age, Name = p.name }); 
    
                i = 0; 
                foreach (var str in query20) 
                { 
                    ++i; 
                    Console.WriteLine(str.Age + " " + str.Name); 
                } 
                Console.WriteLine("个数:" + i); 
    
                //  Except(与非)  
    
                //说明:排除相交项;延迟。即是从某集合中删除与另一个集合中相同的项。 
                //   先遍历第一个集合,找出所有唯一的元素,然后再遍历第二个集合, 
                //   返回第二个集合中所有未出现在前面所得元素集合中的元素。 
                Console.WriteLine("--------------与非操作----------"); 
                var query21 = (from a in pers2 select new { Age = a.age, Name = a.name }) 
                              .Except(from p in ani2 select new { Age = p.age, Name = p.name }); 
    
                i = 0; 
                foreach (var str in query21) 
                { 
                    ++i; 
                    Console.WriteLine(str.Age + " " + str.Name); 
                } 
                Console.WriteLine("个数:" + i); 
    
                 
                //11.210 分区 
                //扩展方法 Take与Skip等分区操作可以用于分页,例如显示5*5个人 
    
                //一页显示的条数 
                int pageSize = 2; 
                //页数计算 
                int numberPages = (int)Math.Ceiling(GetMyList().Count() / (double)pageSize); 
    
                for (int page = 0; page < numberPages; page++) 
                { 
                    Console.WriteLine("-------------------第{0}页-------------------------------", page); 
    
                    var persons = ( from r in GetMyList() select r.name ).Skip( page * pageSize ).Take( pageSize ) ; 
    
                    foreach( var a in persons ) 
                    { 
                        Console.WriteLine( a ) ; 
                    } 
                } 
                //可以看出skip是指忽略多少条,Take是指从取到的记录中取几条 
    
                //11,2,11合并操作 
                //Count用来计算项目数,下面我们选中拥有车超过3辆的人 
                var query22 = from person in GetMyList() where person.list.Count() >= 2 select new { Name = person.name , Age = person.age , Count = person.list.Count() } ; 
                Console.WriteLine( "-----------------------选出拥有车俩3俩以上的人------------" ) ; 
                 
                foreach( var a in query22 ) 
                { 
                    Console.WriteLine( a.Name + " " + a.Age + " " + a.Count ) ; 
                } 
    
                //Sum汇总数字的合 
                //下面,我们用Sum求出所有人年纪的总合(按人名先分组) 
                Console.WriteLine( "-------------------------所有人年纪的总合------------------" ) ; 
                var query23 = from ppp in GetMyList() 
                              group ppp by ppp.name into g 
                              select new 
                                  { 
                                      Name = g.Key, 
                                      AgeSum = (from p in pers select p.age).Sum(), 
                                      Count = g.Count()  
                                  }; 
                foreach (var a in query23) 
                { 
                    Console.WriteLine(a.Name + "   " + a.AgeSum + "  " + a.Count ); 
                } 
                 
                 
                //11.2.12转换 
                //之前我们用到的查询,都是在foreach时才会真正的执行,下面我们的方式是强制立即执行,将结果放数集合数组等容器中 
                List<Person> list = (from p in GetMyList() select p).ToList(); 
                Console.WriteLine("立即执行查询-----------------------"); 
    
                foreach (var a in list) 
                { 
                    Console.WriteLine(a.age + a.name ) ; 
    
                    foreach( var p in a.list ) 
                    { 
                        Console.WriteLine( p.name ) ; 
                    } 
                } 
    
                //接着,我们做一个字典,车对人(一对多) 
                ILookup<string, Person> per111 = (from per in GetMyList() 
                                                   from c in per.list 
                                                   select new 
                                                       { 
                                                           Car = c.name, 
                                                           Person = per 
                                                       }).ToLookup(p => p.Car, p => p.Person); 
                Console.WriteLine( per111.Count ) ; 
                if ( per111.Contains("奔驰") ) 
                {  
                    foreach( var p in per111["奔驰"] ) 
                    { 
                        Console.WriteLine( "有这个车的人:{0}" , p.name ) ; 
                    } 
                } 
                //如果要在非泛型版的集合上使用,可以用Cast方法强制得到类型 
                ArrayList arr = new ArrayList( GetMyList() as ICollection ) ; 
    
                var qqq = from a in arr.Cast<Person>()  where a.name == "aladdin" select a ; 
    
                //11.2.13生成操作符 
                // Range() Empty() Repear()不是扩展方法,而是返回序列的正常静态方法 
                // 在LINQ to Objects中,这些方法可以用于Enumearable类 
                // 有时需要填充一个范围的数字,这时需要用到Range方法,第一个参数做为起始值,第二个是指填充的项目数 
                var values = Enumerable.Range( 1 ,20 ).Select( n => n*3 ) ; 
                foreach( var a in values ) 
                { 
                    Console.Write( a + " " ) ; 
                } 
                //结果1 2 3 4 .....20 
                //比如某个方法,参数是一个集合,我们传一个空进去,就可以用Empty 
                var em = Enumerable.Empty<int>() ; 
    
                var pep = Enumerable.Repeat( "fuck " , 10 ) ; 
                foreach( var a in pep ) 
                { 
                    Console.WriteLine( a ) ; 
                } 
                //Repeat用于把特定元素按指定的重复次数爹代 
    
    
                Console.ReadLine(); 
    
            } 
    
            public static void PrintMyInfo(IEnumerable<Person> en) 
            { 
                foreach (Person per in en) 
                { 
                    Console.WriteLine("姓名:{0} 年龄:{1}", per.name, per.age); 
                } 
            } 
    
            public static IEnumerable<Animal> GetMyAnimalList() 
            { 
                List<Animal> lists = new List<Animal>(); 
    
                Animal p1 = new Animal("aladdin", 21); 
                Animal p2 = new Animal("apple", 22); 
                Animal p3 = new Animal("angel", 30); 
                Animal p4 = new Animal("jacky", 22); 
    
                lists.Add(p1); 
                lists.Add(p2); 
                lists.Add(p3); 
                lists.Add(p4); 
    
                return lists; 
            } 
    
            public static IEnumerable<Person> GetMyList() 
            { 
                List<Person> lists = new List<Person>(); 
    
                Person p1 = new Person("aladdin", 21); 
                Person p2 = new Person("apple", 22); 
                Person p3 = new Person("angel", 30); 
                Person p4 = new Person("jacky", 20); 
                Person p5 = new Person("zhao", 11); 
                Person p6 = new Person("fuck", 33); 
                Person p7 = new Person("emep", 25); 
    
                Person p8 = new Person("xiaoming", 88); 
                Person p9 = new Person("along", 88); 
                Person p10 = new Person("dafei", 99); 
                Person p11 = new Person("bige", 99); 
    
                Person p12 = new Person("feitianlong", 77); 
                Person p13 = new Person("dalianmao", 77); 
                Person p14 = new Person("guixianren", 21); 
                Person p15 = new Person("yuebuqun", 21); 
    
                p1.list.Add(new Cars("奔驰")); 
                p1.list.Add(new Cars("宝马")); 
                p1.list.Add(new Cars("拖拉机")); 
    
                p2.list.Add(new Cars("自行车")); 
                p2.list.Add(new Cars("摩托")); 
    
                p3.list.Add(new Cars("奔驰")); 
                p3.list.Add(new Cars("陆虎")); 
    
                p4.list.Add(new Cars("捷达")); 
                p4.list.Add(new Cars("哈飞")); 
    
                p5.list.Add(new Cars("奔驰")); 
                p5.list.Add(new Cars("宝时捷")); 
    
                p6.list.Add(new Cars("奔驰")); 
                p6.list.Add(new Cars("霸道")); 
    
                p7.list.Add(new Cars("昌河")); 
                p7.list.Add(new Cars("长安之星")); 
    
                lists.Add(p1); 
                lists.Add(p2); 
                lists.Add(p3); 
                lists.Add(p4); 
                lists.Add(p5); 
                lists.Add(p6); 
                lists.Add(p7); 
    
                lists.Add(p8); 
                lists.Add(p9); 
                lists.Add(p10); 
                lists.Add(p11); 
                lists.Add(p12); 
                lists.Add(p13); 
                lists.Add(p14); 
                lists.Add(p15); 
    
                return lists; 
            } 
        } 
    
        class Person 
        { 
            public string name; 
            public int age; 
            public List<Cars> list = new List<Cars>(); 
    
            public Person(string name, int age) 
            { 
                this.name = name; 
                this.age = age; 
            } 
        } 
    
        class Cars 
        { 
            public string name; 
    
            public Cars(string name) 
            { 
                this.name = name; 
            } 
        } 
    
        class Animal 
        { 
            public string name; 
            public int age; 
    
            public Animal(string name, int age) 
            { 
                this.name = name; 
                this.age = age; 
            } 
        } 
    
    } 
    出自:http://www.cnblogs.com/puyunhong/archive/2009/10/22/1588078.html
    冯瑞涛
  • 相关阅读:
    android语音识别 android.speech 包分析
    [Android]MIT App Inventor
    How C/C++ Debugging Works on Android
    Android JNI相关
    Google非官方的Text To Speech和Speech Recognition的API
    Cygwin/MinGW
    VoxForge collect transcribed speech for use with Free and Open Source Speech Recognition Engines
    Voice Search/Actions for Android
    如何查看网页编码
    [转]Python__builtin__与__builtins__的区别与关系(超详细,经典)
  • 原文地址:https://www.cnblogs.com/finehappy/p/1654978.html
Copyright © 2020-2023  润新知