Linq查询

112 阅读9分钟

一、查询过滤:where()

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var news = new[] {
                new {Name="张三",Age=19,Address="北京" },
                new {Name="李四",Age=22,Address="上海" },
                new {Name="王五",Age=34,Address="广州" },
                new {Name="赵六",Age=45,Address="杭州" },
                new {Name="孙琦",Age=25,Address="深圳" },
                new {Name="张玖",Age=45,Address="成都" },
            };
        news.Where(i => i.Age > 20 && i.Address == "深圳").ToList().ForEach(x=> { Debug.Log(x); });//满足条件的所有对象
        var query = from r in news
                    where r.Name.Contains("张")//满足条件的所有对象
                    select r;
        foreach (var temp in query)
        {
            Debug.Log(temp.Name);
        }
    }
    
    //输出结果:{ Name = 孙琦, Age = 25, Address = 深圳 }
    //张三

二、选取数据:Select()、SelectMany()

1.select()*:返回一个对象,对数据进行选取或重新组装

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {       
        var news = new[] {
                new {Name="张三",Age=19,Address="北京" },
                new {Name="李四",Age=22,Address="上海" },
                new {Name="王五",Age=34,Address="广州" },
                new {Name="赵六",Age=45,Address="杭州" },
                new {Name="孙琦",Age=25,Address="深圳" },
                new {Name="钱玖",Age=45,Address="成都" },
            };
        var list = news.Select(i=>new {name=i.Name,age=i.Age });
        foreach (var item in list)
        {           
            Debug.Log(item);            
        }
    }
    
    //输出结果:
    //Name:张三,Age:19
    //Name:李四,Age:22
    //Name:王五,Age:34
    //Name:赵六,Age:45
    //Name:孙琦,Age:25
    //Name:钱玖,Age:45

2. SelectMany():类似于数据库的CROSS JOIN ,参考以下例子

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        List<int> list1 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        List<int> list2 = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        var query = list1.SelectMany(i => list2, (x, y) => new { result = "" + y + "*" + x + "=" + x * y + "" });
        string str = string.Empty;
        foreach (var item in query)
        {
            if (item.result == "9*1=9" || item.result == "9*2=18" ||
                item.result == "9*3=27" || item.result == "9*4=36" ||
                item.result == "9*5=45" || item.result == "9*6=54" ||
                item.result == "9*7=63" || item.result == "9*8=72")
            {
                str += item.result + "\n";
            }
            else
            {
                str += item.result + "\t";
            }
        }
        string[] array = str.Split('\n');
        for (int i = 0; i < array.Length; i++)
        {
            if (i < 3)
            { array[i] = array[i].Substring(0, ((i + 1) * 6)); }
            else if (i > 3)
            { array[i] = array[i].Substring(0, ((i + 1) * 6 + i)); }
            else
            { array[i] = array[i].Substring(0, ((i + 1) * 6 + 2)); }            
            Debug.Log(array[i]);
        }
    }
    
    输出结果:
1*1=1
1*2=2   2*2=4
1*3=3   2*3=6   3*3=9
1*4=4   2*4=8   3*4=12  4*4=16
1*5=5   2*5=10  3*5=15  4*5=20  5*5=25
1*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=36
1*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49
1*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64
1*9=9   2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81

三、联接查询:Join()、GroupJoin()

1.Join():数据1.Join(数据2,数据1.key,数据2.key,查询结果)

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var list1 = new[]  {
                new {id=1,Name="Jack"},
                new {id=2,Name="Wiseman" },
                new {id=3,Name="Witt"},
                new {id=4,Name="Wolf" }
            };
        var list2 = new[] {
                new { id=2,Name="Woodrow"},
                new {id=3,Name="Wooten" },
                new {id=5,Name="Hays" },
                new {id=8,Name="Hayley" }
            };

        var query = list1.Join(list2, item1 => item1.id, item2 => item2.id, (item1, item2) => new { item1, item2 });
        foreach (var item in query)
        {           
            Debug.Log("ID=" + item.item1.id + " " + "Name=" + item.item1.Name);           
            Debug.Log("ID=" + item.item1.id + " " + "Name=" + item.item2.Name);
        }
    }
    
    输出结果:
ID:2,Name:Wiseman
ID:2,Name:Woodrow
ID:3,Name:Witt
ID:3,Name:Wooten

2.GroupJoin():同上,返回数据1的所有元素和根据数据1的key获取的数据2的元素集合,具体请参考以下例子

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var list1 = new[] {
                new {ID=1,Name="张老师" },
                new {ID=2,Name="李老师" },
                new {ID=3,Name="周老师" },
                new {ID=4,Name="王老师" }
            };
        var list2 = new[] {
                new {ID=1,Subject="C#" },
                new {ID=2,Subject="Java" },
                new {ID=3,Subject="lua" },
                new {ID=1,Subject="javacirpt" },
                new {ID=2,Subject="C" },
                new {ID=4,Subject="C++" },
                new {ID=5,Subject="python" },
                new {ID=4,Subject="php" },
                new {ID=6,Subject="html" }
            };        
        Debug.Log("-------查询所有老师教的课程-------\n\n");
        var query = list1.GroupJoin(list2, item1 => item1.ID, item2 => item2.ID, (item1, item2) => new { item1, item2 });
        foreach (var item in query)
        {
            Debug.Log(item.item1.Name + "教" + item.item2.Count() + "门课程,其中有" + 
                string.Join("、", item.item2.Select(i => i.Subject)));            
        }
        //或者这样写,结果一样:        
        Debug.Log("--------------------------\n");
        var query2 = list1.GroupJoin(list2, item1 => item1.ID, item2 => item2.ID, (item1, item2) =>
        new { t = item1.Name, c = item2.Count(), s = string.Join("、", item2.Select(i => i.Subject)) });
        foreach (var item in query2)
        {            
            Debug.Log(item.t + "教" + item.c + "门课程,其中有" + item.s);
        }
        
        Debug.Log("\n------ - 查询没有老师教的课程------ -\n\n");
        var query3 = list2.GroupJoin(list1, item2 => item2.ID, item1 => item1.ID,
        (item2, item1) => new { s = item1.Count() == 0 ? item2.Subject : null });
        string str = string.Empty;
        foreach (var item in query3)
        {
            if (item.s != null)
            {
                str += item.s + ",";
            }
        }        
        Debug.Log("目前没有老师教的课程有" + str.Substring(0, str.Length - 1));
    }
    
    输出结果:
-------查询所有老师教的课程-------
张老师教2门课程,其中有C#、javacirpt

李老师教2门课程,其中有Java、C

周老师教1门课程,其中有lua

王老师教2门课程,其中有C++、php

--------------------------

张老师教2门课程,其中有C#、javacirpt

李老师教2门课程,其中有Java、C

周老师教1门课程,其中有lua

王老师教2门课程,其中有C++、php

-------查询没有老师教的课程-------

目前没有老师教的课程有:python,html

四、分组查询:GroupBy()、ToLookup()

都是根据传入的参数对key进行分组,区别在于GroupBy() 是延迟查询,ToLookup() 不是。

1.GroupBy() 延迟加载

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var news = new[] {
                new {Name="张三",Age=19,Address="上海" },
                new {Name="李四",Age=22,Address="上海" },
                new {Name="王五",Age=34,Address="广州" },
                new {Name="赵六",Age=45,Address="广州" },
                new {Name="孙琦",Age=25,Address="深圳" },
                new {Name="钱玖",Age=45,Address="深圳" },
                new {Name="黄菲",Age=45,Address="北京" }
            };
        var list1 = news.GroupBy(i => i.Address);
        //修改数组最后一条数据
        news[6] = new { Name = "黄菲", Age = 45, Address = "上海" };
        var list2 = news.GroupBy(i => i.Address);
        Debug.Log("-----------list1-----------\n\n");
        foreach (var item in list1)
        {
            Debug.Log("\n---------Address:"+ item.Key+"---------\n");            
            foreach (var item1 in item)
            {                
                Debug.Log("Name:" + item1.Name + " " + "Age:" + item1.Age);
            }
        }
        Debug.Log("\n\n-----------list2-----------\n\n");
        foreach (var item in list2)
        {
            Debug.Log("\n---------Address:" + item.Key + "---------\n");
            foreach (var item1 in item)
            {
                Console.WriteLine("Name:{0},Age:{1}", item1.Name, item1.Age);
                Debug.Log("Name:"+item1.Name+" "+"Age:"+item1.Age);
            }
        }
    }
    
    输出结果:
---------------list1---------------

---------Address:上海---------

Name:张三,Age:19
Name:李四,Age:22
Name:黄菲,Age:45

---------Address:广州---------

Name:王五,Age:34
Name:赵六,Age:45

---------Address:深圳---------

Name:孙琦,Age:25
Name:钱玖,Age:45

---------------list2---------------

---------Address:上海---------

Name:张三,Age:19
Name:李四,Age:22
Name:黄菲,Age:45

---------Address:广州---------

Name:王五,Age:34
Name:赵六,Age:45

---------Address:深圳---------

Name:孙琦,Age:25
Name:钱玖,Age:45

2.ToLookUp()立即加载

将上面代码中的GroupBy 改为 ToLookup

输出结果为:

---------------list1---------------

---------Address:上海---------

Name:张三,Age:19
Name:李四,Age:22

---------Address:广州---------

Name:王五,Age:34
Name:赵六,Age:45

---------Address:深圳---------

Name:孙琦,Age:25
Name:钱玖,Age:45

---------Address:北京---------

Name:黄菲,Age:45

---------------list2---------------

---------Address:上海---------

Name:张三,Age:19
Name:李四,Age:22
Name:黄菲,Age:45

---------Address:广州---------

Name:王五,Age:34
Name:赵六,Age:45

---------Address:深圳---------

Name:孙琦,Age:25
Name:钱玖,Age:45

五、数据排序:OrderBy()、OrderByDescending()、ThenBy()、THenByDescending()

1.OrderBy():根据传入参数对数据源排序(升序)

2.OrderByDescending():与Orderby() 相同,做反向排序(降序)

3.ThenBy():用于多重排序,与OrderBy() 组合,使用于OrderBy() 之后

4.THenByDescending():用于多重排序,与OrderBy() 组合,使用于OrderBy() 之后

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var list2 = new[] {
                new {ID=1,Subject="C#" },
                new {ID=2,Subject="Java" },
                new {ID=3,Subject="lua" },
                new {ID=1,Subject="javacirpt" },
                new {ID=2,Subject="C" },
                new {ID=4,Subject="C++" },
                new {ID=5,Subject="python" },
                new {ID=4,Subject="php" },
                new {ID=6,Subject="html" }
            };      
        Debug.Log("---------Orderby()、ThenBy()---------\n\n");
        var query4 = list2.OrderBy(i => i.ID).ThenBy(i => i.Subject);
        foreach (var item in query4)
        {
            Debug.Log(item);
        }        
        Debug.Log("\n\n---------OrderByDescending()、ThenByDescending()---------\n\n");
        var query5 = list2.OrderByDescending(i => i.ID).ThenByDescending(i => i.Subject);
        foreach (var item in query5)
        {
            Debug.Log(item);
        }
    }
    
    输出结果:
---------Orderby()、ThenBy()---------

{ ID = 1, Subject = C# }
{ ID = 1, Subject = javacirpt }
{ ID = 2, Subject = C }
{ ID = 2, Subject = Java }
{ ID = 3, Subject = lua }
{ ID = 4, Subject = C++ }
{ ID = 4, Subject = php }
{ ID = 5, Subject = python }
{ ID = 6, Subject = html }

---------OrderByDescending()、ThenByDescending()---------

{ ID = 6, Subject = html }
{ ID = 5, Subject = python }
{ ID = 4, Subject = php }
{ ID = 4, Subject = C++ }
{ ID = 3, Subject = lua }
{ ID = 2, Subject = Java }
{ ID = 2, Subject = C }
{ ID = 1, Subject = javacirpt }
{ ID = 1, Subject = C# }

六、集合划分:Take()、Skip()、TakeWhile()、SkipWhile()

    //skip 跳过前10项,取剩余元素
    //skipWhile 跳过小于 5 元素,取剩余元素
    //take 只取前10项,跳过剩余元素
    //takeWhile 只取小于 5 元素,跳过剩余元素
    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        int[] ints = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 };
        var skip = ints.Skip(10).ToList();              //跳过前 10 项元素,取剩余元素
        var skipWhile = ints.SkipWhile(_ => _ < 5).ToList(); //跳过小于 5 元素,取剩余元素
        var take = ints.Take(10).ToList();              //只取前 10 项元素,跳过剩余元素
        var takeWhile = ints.TakeWhile(_ => _ < 5).ToList(); //只取小于 5 元素,跳过剩余元素
        skip.ForEach(_ => Debug.Log(_ + "-"));             //10-11-12-13-14-15-16-17-18-19-                                      
        skipWhile.ForEach(_ => Debug.Log(_ + "-"));        //5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-          
        take.ForEach(_ => Debug.Log(_ + "-"));             //0-1-2-3-4-5-6-7-8-9-        
        takeWhile.ForEach(_ => Debug.Log(_ + "-"));        //0-1-2-3-4-        
        var takeWhile0 = ints.TakeWhile(_ => _ > 5).ToList();//跳过了所有元素,取不到任何元素
        Debug.Log("takeWhile0 数量为:" + takeWhile0.Count);// 0       
    }
    
    输出结果:
10-11-12-13-14-15-16-17-18-19-
5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-
0-1-2-3-4-5-6-7-8-9-
0-1-2-3-4-
takeWhile0 数量为:0

1.Take():返回指定数量的元素

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var list = new[] { 1,2,3,4,5,6,7,8};
        var query = list.Take(5);        
        Debug.Log("-------------Take-------------");
        foreach (var item in query)
        {
            Debug.Log(item);
        }
    }
        
    输出结果:
-------------Take-------------
1
2
3
4
5

2.Skip():跳过指定的元素数量,返回剩余元素

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var list = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        var query = list.Skip(2);
        
        Debug.Log("-------------Skip-------------");
        foreach (var item in query)
        {
            Debug.Log(item);
        }
    }
    
    输出结果:
-------------Skip-------------
3
4
5
6
7
8

3.TakeWhile():返回满足条件的所有元素

注:当第一次检测到条件为false时,将不在检测,返回满足条件的元素

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        var list1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        //由于 1>2 为false(不满足条件),所以1 (包括1)后面的所有元素都不会返回
        var query1 = list.TakeWhile(i => i > 2);
        Debug.Log("-------------TakeWhilei > 2-------------");
        foreach (var item in query1)
        {
            Debug.Log(item);
        }
        var list2 = new[] { 5,6,7,8,9,10 };
        var query2 = list2.TakeWhile(i => i > 4);
        Debug.Log("-------------TakeWhilei > 4-------------");
        foreach (var item in query2)
        {
            Debug.Log(item);
        }        
    }
    
    输出结果:
-------------Skip-------------

-------------TakeWhilei > 4-------------
5
6
7
8
9
10

4.First():取数据中满足条件的第一项元素

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {        
        var list = new[] { 5,6,7,8,9,10 };
        var query = list.First(i => i > 8);
        Debug.Log("-------------First > 8-------------");
        Debug.Log(query);
    }
    
    输出结果:
-------------First > 8-------------
9

5.Last():满足条件的最后一个

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        List<int>list = new List<int>() { 1, 2, 2, 2, 3, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        int a = list.Last();
        int b=list.Last(_ => _<8);
        Debug.Log(a);
        Debug.Log(b);
    }
    
    输出结果:
    10
    7

七、集合运算:Union()、Intersect()、Except()、Distinct()

1.Union():返回两个集合中的并集(两集合重复元素只保留一个)

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        int[] array1 = new int[] { 1, 3, 5, 2, 8, 7, 9 };
        int[] array2 = new int[] { 1, 4, 8, 6, 3, 2 };
        var result = array1.Union(array2);
        Debug.Log("----------Union----------\n");
        foreach (var item in result)
        {
            Debug.Log(item);
        }
    }
    
    输出结果:
----------Union----------

1       3       5       2       8       7       9       4       6

2.Intersect():返回两个集合的交集

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        int[] array1 = new int[] { 1, 3, 5, 2, 8, 7, 9 };
        int[] array2 = new int[] { 1, 4, 8, 6, 3, 2 };
        var result = array1.Intersect(array2);        
        Debug.Log("----------Inersect----------");
        foreach (var item in result)
        {
            Debug.Log(item);
        }
    }
    
    输出结果:
----------Inersect----------

1       3       2       8

3.Except():

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        int[] array1 = new int[] { 1, 3, 5, 2, 8, 7, 9 };
        int[] array2 = new int[] { 1, 4, 8, 6, 3, 2 };
        var result = array1.Except(array2);  
        Debug.Log("----------Inersect----------");              
        foreach (var item in result)
        {
            Debug.Log(item);
        }
    }
    
    输出结果:
----------Inersect----------

5       7       9

4.Distinct():返回集合中非重复的元素

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        int[] int1 = new int[] { 1, 2, 1, 3, 4, 4, 3, 2, 5, 6 };
        var list4 = int1.Distinct();
        foreach (var item in list4)
        {
            Console.Write(item+"\t");
        }
    }
    
    输出结果:
1       2       3       4       5       6

八、汇总聚合:Average()、Max()、Min()、Sum()、Aggregate()、Zip()

Average():计算集合的平均值 只支持int 、long、double、single、deciaml 等值类型

Max():返回集合中的最大值 支持类型同上

Min():返回集合中的最小值 支持类型同上

Sum():计算集合的和 支持类型同上

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        int[] list = new[] { 4, 5, 6, 14, 3, 10 };
        Debug.Log("平均值:" + list.Average());
        Debug.Log("最大值:" + list.Max());
        Debug.Log("最小值:" + list.Min());
        Debug.Log("总和:" + list.Sum());
    }
    
    输出结果:
平均值:7

最大值:14

最小值:3

总和:42

Aggregate():

1.按照传入的条件对元素进行累计运算
2.可传入种子值作为累计计算的初始值,对返回结果进行处理
参考以下两个实例:

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        //按照字符串长度排序输出
        List<string> list = new List<string>() { "red", "yellow", "green", "blue", "paleturquoise", "papayawhip", "peachpuff" };
        int count = list.Count;
        for (int i = 0; i < count; i++)
        {
            string a = list.Aggregate((x, y) => x.Length > y.Length ? x : y);
            list.Remove(a);
            Debug.Log(a);
        }
    }
    
    输出结果:
paleturquoise

papayawhip

peachpuff

yellow

green

blue

red

Zip():

对两个集合中元素进行合并,若两集合元素数量不一致,则返回结果元素数量与元素数量少的一致(即:一个集合是4个元素,一个是3个,返回结果元素是3个)
参考以下例子

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        List<int> list1 = new List<int> { 19, 20, 34, 42, 22, 14, 25 };
        List<string> list2 = new List<string> { "张三", "李四", "王五", "赵二", "牛六", "周玖" };
        var result = list1.Zip(list2, (x, y) => string.Format("{0}今年{1}岁了", y, x));
        foreach (var item in result)
        {
            Debug.Log(item);
        }
    }
    
    输出结果:
张三今年19岁了
李四今年20岁了
王五今年34岁了
趙二今年42岁了
牛六今年22岁了
周玖今年14岁了

九、类型筛选:OfType

    void Start()
    {
        LinqTest();
    }
    void LinqTest()
    {
        object[] objects = { 1, 2, 3, 4, 5, "字符1", "字符2", "字符3" };
        var intList = objects.OfType<int>().ToList();    //找出类型为 Int 的元素
        var stringList = objects.OfType<string>().ToList(); //找出 String 元素
        intList.ForEach(_ => Debug.Log(_ + "-"));    //1-2-3-4-5-       
        stringList.ForEach(_ => Debug.Log(_ + "-")); //字符1-字符2-字符3-       
    }
    
    输出结果:
1-2-3-4-5-
字符1-字符2-字符3-