LINQ使用大全--------List泛型集合常用方法---------------

总体

Where是条件帅选,返回一个IEnumerable<> 泛型接口集合,Select则是构建集合

参考资料:

Find和FirstOrDefault()有什么区别?

 

First,FirstOrDefault,Single,SingleOrDefault的区别

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace List泛型集合
{
    class Program
    {
        static void Main(string[] args)
        {
            //ArrayList的好处是长度可变,可以往里面放任意类型的数据。但是当我们从ArrayList中取数据的时候,取出来的全部是Object类型的数据,最终还要将这个Object类型的数据转换成我们需要的类型数据。这期间就可以发生拆箱操作。费时间。而List泛型集合就能很好的解决这个问题。



            //--------------------------------------Add(); AddRange()添加元素



            //一旦你确定了泛型集合的类型,那么泛型集合里就只能存放该类型数据了。

            //创建泛型集合对象
            List<int> list = new List<int>();
            list.Add(1); //单List的类型是int的时候。Add(int item) Add方法的参数是int类型的。说明只能网里面存int类型的数据

            List<string> listStr = new List<string>();
            listStr.Add("abc");//单List的类型是string的时候。Add(string item) Add方法的参数是string类型的。说明只能网里面存string类型的数据


            List<int[]> listArray = new List<int[]>(); //list里面接收的是一个int[]数组。
            listArray.Add(new int[] { 1, 2, 3 });


            List<int[]> listIEnumerable = new List<int[]>();

            //AddRange(IEnumerable<int[]> collection); AddRange()方法的参数接收的是一个List<int[]>的集合。
            listIEnumerable.AddRange(new List<int[]>() { new int[] { 1, 2, 3 }, new int[] { 4, 5, 6 } });



            //--------------------------------------Insert()  ;InsertRange()添加


            List<int> list1 = new List<int>() { 1, 2, 3 };

            list1.Insert(0, 5); //从list1这个泛型集合索引下标的0处插入一个5



            //InsertRange(int Index, IEnumerable<int> collection);注意括号中的第二个参数需要的是一个IEnumerable<int>类型。根据里氏转换定律得知:一个地方需要一个父类,我们可以给它一个子类。因为List<T>是继承自IEnumerable<T>所以下面的参数是给了它一个List<int>
            list1.InsertRange(1, new List<int> { 4, 5, 6 });//从listInt这个泛型集合索引下标的1处插入一个List<int>集合

            foreach (int i in list1)
            {
                Console.WriteLine(i); //输出5,1,2,3
            }



            //--------------------------------------Remove();RemoveRange()删除

            List<int> list2 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8 };
            list2.Remove(1); //Remove(int item)  删除list2集合中 “1” 这个元素。

            list2.RemoveAt(0);//RemoveAt(int index) 删除list2集合中索引下标为0的这个元素

            list2.RemoveRange(0, 2);//RemoveRange(int index,int count) 删除一定范围内的元素。从索引下标0处开始删除,总共删除2个元素。


            //RemoveAll(Predicate<int> math) //接收的是一个拉姆达表达式
            list2.RemoveAll(p => p > 2 && p <= 5); //删除list2集合中 大于2并且小于等于5之间的元素

            foreach (int i in list2) 
            {
                Console.WriteLine(i);
            }


            //--------------------------------------Clear()清空所有元素

            List<int> list3 = new List<int>() { 1, 2, 3, 4, 5, 6 };
            list3.Clear();



            //--------------------------------------Contaion()包含 

            List<int> list4 = new List<int>() { 1, 2, 3, 4, 5, 6 };
            bool b = list4.Contains(2); //Contains(int item) 检查list4泛型集合中是否包含了“2”这个元素。如果包含就返回true 不包含就返回false







            //--------------------------------------First()   Last();


            List<int> list5 = new List<int>() { 1, 2, 3, 4, 5, 6 };

            //假如list5这个泛型集合没有任何一项元素。那么调用First方法就会抛异常,提示:序列不包含任何元素


            //First()方法的返回值为int类型。为什么是int类型?那是因为list5这个集合在什么的时候就已经确定它是一个int类型的泛型集合了List<int>
            int t1 = list5.First();//返回list5这个泛型集合中第一个元素 t1的值为1。假如当list5这个泛型集合没有包含任何元素的时候,即:
            //List<int> list5 = new List<int>() { };
            //int t1 = list5.First(); 这里会报错:提示:序列不包含任何元素


            int t2 = list5.First(r => r > 4); //返回满足拉姆达表达式的第一个元素; list5中有5,6等元素是>4的,既然要返回满足条件的第一个元素。那么t2的值为5

            //FindAll()方法返回值为一个List<int> 泛型集合 。返回满足拉姆达表达式的所有元素
            List<int> t3 = list5.FindAll(r => r < 5); //t3的元素为 1,2,3,4


            //Last():获取list5这个集合中的最后一个元素
            int t4 = list5.Last();
            Console.Write(t4); //输出6


            //Last(r=>r<4):获取带筛选条件以后的新集合中的第最后一个元素
            int t5=list5.Last(r=>r<4);
            Console.Write(t5); //输出:3



            //--------------------------------------Single();

            List<int> list6 = new List<int>() { 1, 2, 3, 4, 5, 6 };
            //如果集合没有任何元素,会抛异常,如果大于一个元素也会抛异常
            //返回序列中满足指定条件的唯一元素;如果有多个这样的元素存在,则会引发异常
            //int t4 = list6.Single(r => r > 3); //这里会抛异常,提示:序列包含一个以上的匹配元素。因为list6泛型集合里有4,5,6等多个元素是大于3的,不符合“唯一”的条件。(通俗的说:我要在list6这个集合中查找一个大于3的元素,并且我只要一个大于3的元素,如果你给我两个也不行,反正我只要一个。你给多了,或者一个都不给,我都会抛异常。)

            //int t5 = list6.Single(r => r > 6);//这里会抛异常,提示:序列不包含任何匹配元素。(我要一个元素,可是你一个元素也没给我。我就抛异常了。)

            int t6 = list6.Single(r => r > 5);//t6的值为6。 不会抛异常。因为list6泛型集合里只有,6等元素是大于5的。

            

            //int t7 = list6.Single(); //会抛异常:提示:序列包含“一个以上”的匹配元素。

            //如果 List<int> list6 = new List<int>() {1}; 
            //int t7 = list6.Single();泛型集合里“有且只包含一个元素”的时候,调用Single()方法就不会抛异常了。






            //--------------------------------------FirstOrDefault();



            List<int> list7 = new List<int>() { 1, 2, 3, 4, 5, 6 };
            //假如list7这个泛型集合没有任何一项元素,那么FirstOrDefault方法的默认返回值为0 而不会报错。(注:如果泛型集合的元素为空,FirstOrDefault方法的默认返回值是根据泛型的类型来定的。int类型的默认值就是0。string类型的默认值为null)
           

            int tt1 = list7.FirstOrDefault(); //返回list7这个泛型集合中第一个元素 tt1的值为1。假如单list7这个泛型集合里没有任何元素的时候 ,即:
            //List<int> list7 = new List<int>(){};
            //int tt1 = list7.FirstOrDefault(); //tt1的值为默认为0 ;而不会报错。(这里之所以默认值为0是因为list7是一个int类型的泛型集合。而int的默认值就是0 如果list7是一个string类型的泛型集合的话。那么tt1的默认值就是null。因为string类型的默认值就是null)
            //Console.WriteLine("tt1的值为{0}", tt1); //输出:tt1的值为0




            int tt2 = list7.FirstOrDefault(r => r > 2); //返回满足括号中朗姆达表达式的第一个值:list7这个泛型集合中有3,4,5,6 等元素>2 ;所以既然是返回满足朗姆达表达式的第一个值。所以tt2的值为3

            int tt3 = list7.FirstOrDefault(r => r == 8);
            Console.WriteLine("tt3的值为", +tt3);//输出: tt3的值为___   即:tt3的值为空 因为list7里没有8这个元素。所以找不到。既然找不到8这个元素,所以就什么都不会输出了。(注:这里tt3的值不是为0。而是为空)




            //========================================================

            //Find方法和FirstOrDefault方法效果相同,都是返回满足条件的第一个元素,如果没有该元素,则返回null。


            //1>Find方法是.netFramework2.0的,而FirstOrDefault是3.5的。

            //2>Find方法只能在List<T>上使用,而后者能更广泛应用在IEnemerable<T>上。

            //>Find最终是建立在Array的查找之上,而在IEnemerable上的FirstOrDefault是使用foreach查找的。因此,Find速度会比FirstOrDefault快很多,据测试可能会快一倍以上。


            //=========================================================




            //--------------------------------------Find()    FindAll(); 

            
            List<int> list8 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            //假如list8这个泛型集合没有任何一项元素。那么Find方法的默认值返回值为0 而不会报错。(注:如果泛型集合的元素为空,Find方法的默认返回值是根据泛型的类型来定的。int类型的默认值就是0。string类型的默认值为null)


            int t8 = list8.Find(r => r < 6); //返回满足括号中朗姆达表达式的第一个元素 ;list8泛型集合中有1,2,3,4,5等元素是<6的 ,既然是返回满足朗姆达表达式的第一个值 所以:t8的值为1


            int t9 = list8.Find(r => r > 6); //list8泛型集合中有7,8,9等元素的值是>6的。既然是返回满足朗姆达表达式的第一个值 所以:t9的值为7

            List<int> t10 = list8.FindAll(r => r > 2);//list8泛型集合中有3,4,5,6,7,8,9等元素的值是>2的。所有t10的元素为3,4,5,6,7,8,9
			
			//我们来看看这个FindAll()方法为我们做的事情:1.遍历t10这个泛型集合,将集合中的每一项逐条传递到括号中的匿名委托中去,而匿名委托其实就是返回值是布尔类类型,参数是泛型类型的委托,具体请看最下面的FinAll()详解
            


            //--------------------------------------Any() 只要有一个元素满足条件就返回true。否则返回false

            List<int> list9 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            //Any()检查list9泛型集合中的元素是否满足括号中的拉姆达表达式。只要有一个元素满足条件就返回true。否则返回false
            bool b1 = list9.Any(r => r < 8); //b1的值为true;因为list9中有1,2,3,4,5,6,7等元素小于8
            bool b2 = list9.Any(r => r > 8); //b2的值为true;因为list9中 元素9是大于8的
            bool b3 = list9.Any(r => r > 10);//b3的值为false;因为list9中,没有任何一个元素大于10



            //--------------------------------------All() 只有集合的“所有元素”都满足条件就返回true。否则返回false

            List<int> list10 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

            bool b4 = list10.All(r => r > 5); // 因为list10这个泛型集合里有1,2,3,4等元素是<5的。没有达到达到所有元素都>5这个条件。所以b4的值为 false

            bool b5 = list10.All(r => r < 10);//在list10这个泛型集合中,所有的元素都是<10的。所以b5的值为true



            //--------------------------------------Where()

            List<int> list15 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            var b6 = list15.Where(r => r > 6); //查询list15这个泛型集合中大于6的元素。注意这个Where的返回值是一个IEnumerable<int> 泛型接口的集合
            b6.ToList().ForEach(new Action<int>(r=>Response.Write(r))); //将b6这个泛型接口集合转换成List集合,然后遍历,打印出: 7,8,9


            var queryList = from item in list15
                            where (item > 5) //筛选出list15泛型集合中大于5的元素。
                            select (item);//将筛选出来的所以元素投影到新表中。即:根据where条件构建一个新的集合。
                                    
            foreach (var item in queryList)
            {
                Response.Write(item); //输出6,7,8,9
            }
            //也可以这样遍历
            queryList.ToList().ForEach(new Action<int>(r => Response.Write(r))); //输出6,7,8,9


            //--------------------------------------Exists() 是否包含与指定谓词所定义的条件相匹配的元素。如果包含就返回true。否则就返回false

            List<int> list16 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            bool b7 = list16.Exists(r => r > 5);//检查list16这个泛型集合中是否有 大于5的元素。因为list16泛型集合中有6,7,8,9等元素大于5所以 b7的值为true


            

            //--------------------------------------ToArray() 将List<T>泛型集合转换成数组

            List<int> list11 = new List<int>() { 1, 2, 3, 4, 5, 6 };
            int[] arr = list11.ToArray(); //将一个list<int> 泛型集合转换成一个int类型的数组;这里可以转换是因为,List<int>里存放的数据本身就是int类型的


            //--------------------------------------ToList() 将数组转换成List<T>泛型集合

            int[] arr1 = new int[] { 1, 2, 3, 4, 5, 6 };
            List<int> list12 = arr1.ToList(); //将一个int[]类型数组转换成List<int>泛型集合;这里可以转换是因为,List<int>里存放的数据是int类型的。而arr数组存放的数据也是int 类型的



            //--------------------------------------Reverse() 元素反转

            List<int> list13 = new List<int>() { 1, 2, 8, 4, 5, 6 };
            list13.Reverse(); //将list13这个泛型集合里的元素顺序反转。注意:是反转,不是降序排序



            //--------------------------------------Sort() 升序排序

            List<int> list14 = new List<int>() { 2, 8, 4, 1, 6, 5, 3, 7 };
            list14.Sort(); //将list14这个泛型集合里的元素按照升序排序
            Console.WriteLine("---------------");
            foreach (int i in list14)
            {
                Console.WriteLine(i); //输出:1,2,3,4,5,6,7,8
            }
			//或者这样遍历list14这个集合
			list14.ForEach(new Action<int>(r => { Response.Write(r); })); //输出:1,2,3,4,5,6,7,8
            
			
			//----------------------------------Count()  获取数据项数
			
			List<int> list17 = new List<int>() { 2, 8, 4, 1, 6, 5, 3, 7 };

            //Count()表示获取list17这个集合有几项数据
            int a= list17.Count();
            Console.Write(a);  //输出:8

            //Count(r => r > 5)表示获取满足筛选条件的数据总共有多少条
            int b = list17.Count(r => r > 5);
            Console.Write(b); //输出:3
			

            Console.ReadKey();

                
        }
    }
}

 

 

 

 

 

 

FindAll()详解

 

class preson
{
    public void Test()
    {
        var list = new List<student>() //创建一个list泛型集合
        {
            new student{Name="张三",Age=15},
            new student{Name="王五",Age=17}            
        };


        Predicate<student> pr = new Predicate<student>(Pred); //pr是一个委托,这个委托指向pred方法; 这句也可以简写成:redicate<student> pr=pred;
      
        List<student> b = list.FindAll(pr);

        //这个FindAll 做的事情就是:1.遍历这个list集合 2.将list集合中的每一项逐条传递到 Pred这个方法中。例如:首先将new student{Name="张三",Age=15}这个对象传递到Pred方法中,因为这个对象的Age属性是15,它小于16,所以方法就会返回false,返回false的数据就会丢掉。接着会传递new student{Name="王五",Age=17} 这个对象到Pred这个方法中,因这个对象的Age属性是17,它大于16,所以方法会返回true,如果返回true,那么new student{Name="王五",Age=17}这条数据就会被返回,并保存到  b 这个泛型集合中去。3.最后b这个泛型集合里就保存了list中所有Age大于16的对象
    }

    public bool Pred(student stu)
    {
        return stu.Age > 16;
    }
}

 

list.ForEach()详解

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace 泛型
{
    public class Studen
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var list=new List<Studen>()
            {
                new Studen{Name="曹操",Age=46},
                new Studen{Name="刘备",Age=52},
                new Studen{Name="孙策",Age=18}
            };

            list.ForEach(new Action<Studen>(r => { Response.Write(r.Name + r.Age); })); //打印出:曹操46 刘备52 孙策18 

            //其实这个ForEach,就是遍历了list这个集合。但是这个ForEach方法没有返回值。它仅仅是对list这个集合中的 内容进行处理,或打印


            //在看下面这个例子:
            List<int> li = new List<int>() { 0, 1, 2, 5, 4, 7 };
            List<int> result = new List<int>();

            li.ForEach(x => { x = x + 1; result.Add(x); }); //给li集合中每个元素加1,然后给加1后的值添加到result这个集合中去

            result.ForEach(r => Response.Write(r));//遍历result这个集合。  输出:123658 
        }
    }
}

 

OrderBy  升序排序   OrderByDescending 降序排序   (组合排序 ThenBy   ThenByDescending)

 

特别要注意:组合排序的时候,对第一个字段排序的时候用OrderBy  或 OrderByDescending 对第第二个,及后面的排序要用ThenBy   或 ThenByDescending

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 泛型
{
    public class Studen
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {

            List<int> list18 = new List<int>() { 2, 8, 4, 1, 6, 5, 3, 7 };

            //正序排列
            List<int> a = list18.OrderBy(r => r).ToList(); //按照list18中的项排序。
            a.ForEach(r => Console.WriteLine(r)); //输出:1,2,3,4,5,6,7,8



            //倒序排序
            //输出:8,7,6,5,4,3,2,1
            list18.OrderByDescending(r => r).ToList().ForEach(r => Console.Write(r));


            //-------------------例二

            //根据年龄进行升序排列

            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46},
                new Studen{Id=2, Name="刘备",Age=52},
                new Studen{Id=3, Name="孙策",Age=18},
                new Studen{Id=4, Name="吕布",Age=52}
            };

            //我们看到OrderBy(Func<Studen,Tkey> keySelector) 它里面是一个带一个为Student类型的参数,返回值为Tkey的委托,以后当我们看到这个Tkey就应该要知道,这个Tkey就是表示从你的参数类型中取一个属性。 而这个参数是Student,从它里面去取一个属性。这里我们取的是Age这个属性。
            //所以这里就是按照Student类中的Age属性来进行排序
            var dd = list.OrderBy(r => r.Age).ToList();

            //这里输出:孙策18  曹操46 刘备52 吕布52
            dd.ForEach(r => Console.WriteLine(r.Name + r.Age));


            Console.WriteLine();


            //根据年龄进行倒序排列

            //这里输出:刘备52  吕布52 曹操46  孙策18 
            list.OrderByDescending(r => r.Age).ToList().ForEach(r => Console.WriteLine(r.Name + r.Age));


            Console.WriteLine();

            //现在我们来看看多字段组合排序
            //需求:先根据年龄进行升序排序,后再根据Id进行排序

            //特别要注意:当使用组合排序的时候,第一个排序先使用OrderBy()或者OrderByDescending()进行排序。然后后面的排序,用ThenBy()或者ThenByDescending()进行排序
            //例如:在先进行年龄排序的时候,我先用OrderBy()进行排序了。年龄排序完毕后,我再使用ThenBy()语句对Id进行排序。(ThenBy()也是排序的意思。)
            list.OrderBy(r => r.Age).ThenBy(r => r.Id).ToList().ForEach(r => Console.WriteLine(r.Id + ":" + r.Name + ":" + r.Age));

            //这里输出: 首先根据年龄进行升序排序了。然后我们对Id进行排序,因为吕布年龄和刘备年龄一样大,既然根据Id进行升序排序,刘备的Id是3,而吕布的Id是4 所以吕布就排在刘备的后面了。
            //3:孙策:18
            //1:曹操:46
            //2:刘备:52
            //4:吕布:52
            Console.ReadKey();

        }


    }
}

 

排序

 

List<string> list = new List<string>() { "abc", "EDdeed", "eddeeeee", "DEFrr" };
var aa = (from item in list
          where item.Length > 3
          orderby item.Length  ascending//descending 
          //orderby item.Length ascending, item.GetHashCode() descending 多字段排序(根据字符串的长度,和字符串的HashCode进行排序)
          select item).ToList();

 

 

 

 

 

Select 投影方法

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 泛型
{
    public class Studen
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46},
                new Studen{Id=2, Name="刘备",Age=52},
                new Studen{Id=3, Name="孙策",Age=18},
                new Studen{Id=4, Name="吕布",Age=52}
            };


            //投影方法Select

            //需求,从list集合中获取Id,和Name的值,以新的集合返回

            //做法1
            var a = list.Select(r => new Studen() { Id = r.Id, Name = r.Name }).ToList();

            a.ForEach(r => Console.WriteLine( r.Id + ":" + r.Name));
            //打印出:
            //1:曹操
            //2:刘备
            //2:孙策
            //4:吕布

            //做法2  直接使用匿名类来接收
            var b = list.Select(r => new { Id = r.Id, Name = r.Name }).ToList();
            b.ForEach(r => Console.WriteLine(r.Id + ":" + r.Name));
            //打印出:
            //1:曹操
            //2:刘备
            //2:孙策
            //4:吕布

            //因为匿名类重写了ToString()方法,所以我们打印打印的时候可以这样写
            b.ForEach(r => Console.WriteLine(r.ToString()));
            //打印出:
            //{Id=1, Name="曹操"}
            //{Id=2, Name="刘备"}
            //{Id=3, Name="孙策"}
            //{Id=4, Name="吕布"}
            Console.ReadKey();

        }
    }
}

 

Join 连表查询

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 泛型
{
    public class Studen
    {
        public int Id { get; set; }

        public int CountryId { get; set; } //做外键使用。与countrylist集合做连表使用的
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class Country
    {
        /// <summary>
        /// 国家编号
        /// </summary>
        public int CountryId { get; set; }
        /// <summary>
        /// 国家名字
        /// </summary>
        public string CountryName { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {

            //-----------分页(假分页)

            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46,CountryId=1},
                new Studen{Id=2, Name="刘备",Age=52,CountryId=2},
                new Studen{Id=3, Name="孙策",Age=18,CountryId=3},
                new Studen{Id=4, Name="曹植",Age=52,CountryId=1}
            };

            var countrylist = new List<Country>()
            {
                new Country{CountryId=1,CountryName="魏国"},
                new Country{CountryId=2,CountryName="蜀国"},
                new Country{CountryId=3,CountryName="吴国"},
             
            };


            //假如上面是两个表  :需求:获取学生的名称,和所属的国家,作为一个新的集合返回
            //T-SQL:select s.Name,c.CountryName from list s inner join countrylist c on (s.CountryId=c.CountryId)
            //第一个参数:表示list这个表要与哪个表进行连表查询。
            //第二个参数和第三个参数:表示list集合的CountryId字段的值等于countrylist表的CountryId字段的值。用于连表
            //第四个参数:s,c表示两个表,即list表和countrylist,然后从s表中取去Name字段,从c表中取出CountryName字段,然后组成一个新的集合返回
            var newList = list.Join(countrylist, s => s.CountryId, c => c.CountryId, (s, c) => new { s.Name, c.CountryName }).ToList();




            Console.ReadKey();

        }


    }
}

 

GroupBy分组

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 泛型
{
    public class Studen
    {
        public int Id { get; set; }

        public int CountryId { get; set; } //做外键使用。与countrylist集合做连表使用的
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class Country
    {
        /// <summary>
        /// 国家编号
        /// </summary>
        public int CountryId { get; set; }
        /// <summary>
        /// 国家名字
        /// </summary>
        public string CountryName { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {

            //-----------分页(假分页)

            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46,CountryId=1},
                new Studen{Id=2, Name="刘备",Age=52,CountryId=2},
                new Studen{Id=3, Name="孙策",Age=18,CountryId=3},
                new Studen{Id=4, Name="曹植",Age=52,CountryId=1}
            };


            //需求:将list按照CountryId字段进行分组 (魏国有2个人,吴国和蜀国都是一个人,所以这里应该是分成了3组。)

            //根据list集合中的Id来进行分组,然后就获取到了分组后的集合
            var grouedList = list.GroupBy(s => s.CountryId).ToList();
            
            //那我们想知道这个grouedList到底有几组数据。怎么做呢?
            grouedList.ForEach(r => Console.WriteLine("分组号:"+r.Key)); //这个r.key就是每个分组的序列号
            //打印出:
            //分组号:1
            //分组号:2
            //分组号:3

            //或者这样就可以直接打印出到底分了几组
            Console.WriteLine(grouedList.Count()); //打印出:3

            //现在我们要查看每组的内容怎么看呢?
            grouedList.ForEach(a =>
            {
                Console.WriteLine("--------分组号:" + a.Key+"--------");
                a.ToList().ForEach(b => Console.WriteLine(b.Id + "-" + b.Name + "-" + b.Age + "-" + b.CountryId));

            });


            Console.ReadKey();

        }


    }
}

 

 

 

 

 

 

 

 

 

Linq语法

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 泛型
{
    public class Studen
    {
        public int Id { get; set; }

        public int CountryId { get; set; } //做外键使用。与countrylist集合做连表使用的
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class Country
    {
        /// <summary>
        /// 国家编号
        /// </summary>
        public int CountryId { get; set; }
        /// <summary>
        /// 国家名字
        /// </summary>
        public string CountryName { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {

            //-----------分页(假分页)

            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46,CountryId=1},
                new Studen{Id=2, Name="刘备",Age=52,CountryId=2},
                new Studen{Id=3, Name="孙策",Age=18,CountryId=3},
                new Studen{Id=4, Name="曹植",Age=52,CountryId=1}
            };

            //var countrylist = new List<Country>()
            //{
            //    new Country{CountryId=1,CountryName="魏国"},
            //    new Country{CountryId=2,CountryName="蜀国"},
            //    new Country{CountryId=3,CountryName="吴国"},
             
            //};




            //需求: 将从list集合中查找出来的CountryId=1的集合
            //T-SQL:select * from list s where s.CountryId=1

            //将它翻译成Linq语法
            //语句以from 开始,然后先取个别名,别名就叫s ,这个别名是谁的别名呢? in list 就表示这个别名是list的别名。 
            //所以from s in list  就相当于t-sql中的 from list
            var a = (from s in list
                     //现在开始带条件了, where就是条件语句。
                     //所以where s.CountryId==1 就相当于t-sql中的where s.CountryId=1
                     where s.CountryId == 1

                     //最后就差t-sql语句中的select 了。而 select s 这个s其实就是相当于list集合中的所有的元素,所以select s 就相当于t-sql语句中的select * 
                     select s).ToList();


            //需求:从list集合中找出CountryId=1的集合中的Nmae属性的值,然后以新的集合返回
            var b =( from s in list
                    where s.CountryId == 1
                    select new { s.Name ,s.CountryId}).ToList();

            Console.ReadKey();

        }


    }
}

 

Linq 排序 orderby    (ascending,descending)

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Linq排序
{

    public class Studen
    {
        public int Id { get; set; }

        public int CountryId { get; set; } //做外键使用。与countrylist集合做连表使用的
        public string Name { get; set; }
        public int Age { get; set; }


    }

    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46,CountryId=1},
                new Studen{Id=2, Name="刘备",Age=52,CountryId=2},
                new Studen{Id=3, Name="孙策",Age=18,CountryId=3},
                new Studen{Id=4, Name="曹植",Age=52,CountryId=1}
            };

            //将list集合按照年龄进行排序
            var queryList = (from f in list
                             orderby f.Age descending    //descending就表示根据年龄进行倒序排序,如果想进行升序排序可以用ascending关键字。如果不加关键字默认就是升序排序                            
                             select (f)).ToList();
            //queryList.ForEach(r => Response.Write("Id=" + r.Id + " Name=" + r.Name + " Age=" + r.Age + " CountryId=" + r.CountryId+"<br/>"));
            //输出:
            //Id=2 Name=刘备 Age=52 CountryId=2
            //Id=4 Name=曹植 Age=52 CountryId=1
            //Id=1 Name=曹操 Age=46 CountryId=1
            //Id=3 Name=孙策 Age=18 CountryId=3

            //Linq进行多字段组合排序

            //需求: 将list集合按照年龄进行升序排序,然后按照Id进行降序排序
            var qList = (from f in list
                             orderby f.Age ascending,f.Id descending                               
                             select (f)).ToList();
            qList.ForEach(r => Response.Write("Id=" + r.Id + " Name=" + r.Name + " Age=" + r.Age + " CountryId=" + r.CountryId + "<br/>"));
            //输出
            //Id=3 Name=孙策 Age=18 CountryId=3
            //Id=1 Name=曹操 Age=46 CountryId=1
            //Id=4 Name=曹植 Age=52 CountryId=1    //在年龄都是一样的情况下,Id是降序排序的,所以Id=4的这条数据排在前面
            //Id=2 Name=刘备 Age=52 CountryId=2
        }
    }
}

 

 

Linq  多表连接查询 Join

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Linq连表操作
{
    public class Studen
    {
        public int Id { get; set; }

        public int CountryId { get; set; } //做外键使用。与countrylist集合做连表使用的
        public string Name { get; set; }
        public int Age { get; set; }
    }

    public class Country
    {
        /// <summary>
        /// 国家编号
        /// </summary>
        public int CountryId { get; set; }
        /// <summary>
        /// 国家名字
        /// </summary>
        public string CountryName { get; set; }
    }
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46,CountryId=1},
                new Studen{Id=2, Name="刘备",Age=52,CountryId=2},
                new Studen{Id=3, Name="孙策",Age=18,CountryId=3},
                new Studen{Id=4, Name="曹植",Age=52,CountryId=1},

                new Studen{Id=5, Name="吕布",Age=56,CountryId=4}
            };

            var countrylist = new List<Country>()
            {
                new Country{CountryId=1,CountryName="魏国"},
                new Country{CountryId=2,CountryName="蜀国"},
                new Country{CountryId=3,CountryName="吴国"},

            };

            //内连接 inner join

            var queryList = (from l in list
                             join c in countrylist
                             on l.CountryId equals c.CountryId
                             select new { l.Id, l.Name, c.CountryName }).ToList();
            queryList.ForEach(r => Response.Write("Id=" + r.Id + " Name=" + r.Name + " CountryName=" + r.CountryName + "<br/>"));
            //输出:
            //Id=1 Name=曹操 CountryName=魏国
            //Id=2 Name=刘备 CountryName=蜀国
            //Id=3 Name=孙策 CountryName=吴国
            //Id=4 Name=曹植 CountryName=魏国




            //外连接 (很少用,不是重点)
            var qList = (from l in list
                         join c in countrylist.DefaultIfEmpty()
                         on l.CountryId equals c.CountryId into lc  //这个lc其实就是countrylist集合的临时标识
                        
                         //from s in lc.DefaultIfEmpty(new Country() { CountryId = 0, CountryName = "未知" }) 
                         from s in lc.DefaultIfEmpty() //DefaultIfEmpty:表示返回指定序列的元素;如果序列为空,则返回单一实例集合中的类型参数的默认值,例如 int默认值就是0 string 默认值就是 null (我的理解就是:list是左表,countrylist是右表,如果左表有5条数据,它根据CountryId这个字段连接右表后,因为左表有CountryId=4这条数据,而右表没有CountryId=4的这条数据,此时左表的数据应该全部显示,而右表没有CountryId=4的这条数据,应该显示为未知)
                         select new
                         {
                             l.Id,
                             l.Name,
                             HH = s == null ? "未知" : s.CountryName //因为右表没有CountryId=4的这条数据,所以在外连接查询的过程中,做表对应的某条数据,在又表中可能不存在,即左表有CountryId=4的这条数据,而右表中CountryId=4的这条数据可能不存在。这样就出现这条数据为null。因为在匿名类中,null是无法作为匿名类属性的值的。所以如果右表中的某条数据如果不存在,即为null的情况下,我们应该给它赋初始值,所以这里就出现了当s==null的时候,我们就给它赋“未知”这个初始值,如果不为null的话,就给它赋s.CountryName这个值。当然如果不想在这里写这个三元运算符判断的话,也可以在from这条语句这里这么写:from s in lc.DefaultIfEmpty(new Country() { CountryId = 0, CountryName = "未知" }) 
                             

                         }).ToList();
            qList.ForEach(r => Response.Write("Id=" + r.Id + " Name=" + r.Name + " CountryName=" + r.HH + "<br/>"));
            //Id=1 Name=曹操 CountryName=魏国
            //Id=2 Name=刘备 CountryName=蜀国
            //Id=3 Name=孙策 CountryName=吴国
            //Id=4 Name=曹植 CountryName=魏国
            //Id=5 Name=吕布 CountryName=未知
        }
    }
}

 

LInq 分组查询  grou by

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Linq分组查询
{
    public class Studen
    {
        public int Id { get; set; }
        public int CountryId { get; set; } 
        public string Name { get; set; }
        public int Age { get; set; }
    }
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            var list = new List<Studen>()
            {
                new Studen{Id=1, Name="曹操",Age=46,CountryId=1},
                new Studen{Id=2, Name="刘备",Age=52,CountryId=2},
                new Studen{Id=3, Name="孙策",Age=18,CountryId=3},
                new Studen{Id=4, Name="曹植",Age=52,CountryId=1},

                new Studen{Id=5, Name="吕布",Age=56,CountryId=4}
            };

            //需求:从list集合中查询CountryId=1的集合
            var queryList = (from c in list
                            group c by c.CountryId).ToList();

            //Response.Write("根据CountryId这个字段来分组,总共分了" + queryList.Count() + "组"); //这里输出:根据CountryId这个字段来分组,总共分了4组 

            //然后我们来看看这4组中 具体有哪些值

            queryList.ForEach(r=>{ Response.Write("--------------第"+r.Key+"组-----------<br/>");
            r.ToList().ForEach(c => Response.Write("Id=" + c.Id + " Name=" + c.Name + " Age=" + c.Age + " CountryId=" + c.CountryId + "<br/>"));
            });

            //打印出:
            //--------------第1组-----------
            //Id=1 Name=曹操 Age=46 CountryId=1
            //Id=4 Name=曹植 Age=52 CountryId=1
            //--------------第2组-----------
            //Id=2 Name=刘备 Age=52 CountryId=2
            //--------------第3组-----------
            //Id=3 Name=孙策 Age=18 CountryId=3
            //--------------第4组-----------
            //Id=5 Name=吕布 Age=56 CountryId=4

        }
    }
}
//根据keyword进行分组,然后取AddTime最大的那条数据
var aa = sa.UserKeyword.GroupBy(r => r.Keyword).Select(
		a => (new { name = a.Key, count = a.Count(),addtime= a.Max(i=>i.AddTime),result=a })
	).ToList();

//GroupBy(r=>new{r.UserId,r.Keyword})表示根据UserId和Keyword两个字段来分组
var bb = sa.UserKeyword.GroupBy(r => new {r.UserId,r.Keyword }).Select(
		a => (new {name = a.Key, count = a.Count(), addtime = a.Max(i => i.AddTime) })
	).ToList();

例子

 

public class HomeController : Controller
{
    public ActionResult Index()
    {
        List<Student> list = new List<Student>()
        {
            new Student{ Id=1, Name="张三", UserId=11, AddTime=Convert.ToDateTime("2016-10-12")},
            new Student{ Id=2, Name="李四", UserId=22, AddTime=Convert.ToDateTime("2016-10-13")},
            new Student{ Id=3, Name="李四", UserId=22, AddTime=Convert.ToDateTime("2016-10-11")},
            new Student{ Id=4, Name="王五", UserId=33, AddTime=Convert.ToDateTime("2016-10-14")},
        };


        var items = (from s in list
                    group s by new { s.Name, s.UserId } into t //根据Name和UserId进行分组
                    select new
                    {
                        name = t.Key,
                        maxTime = t.Max(r => r.AddTime), //取最大时间的那条数据
                        result = t.ToList() //这个result中包含了Id,Name,UserId,AddTime信息
                    }).ToList();
		
		
        List<Student> listB = new List<Student>();
        foreach (var item in items)
        { 
            var student=new Student();
            student.Id=item.result.FirstOrDefault(r=>r.AddTime==item.maxTime).Id;
            student.Name=item.result.FirstOrDefault().Name;
            student.UserId=item.result.FirstOrDefault().UserId;
            student.AddTime=item.maxTime;
            listB.Add(student);
        };
        return View();
    }

}
public class Student
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public string Name { get; set; }
    public DateTime AddTime { get; set; }
}

 

 

 

 

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值