C#中Linq的基礎操作

前言

LinqC#中提供語言級查詢功能和高階函數 API,以便能夠編寫具有很高表達力度的聲明性代碼。使用Linq能夠讓我們的代碼更加簡潔。下面先來看一個問題:現在有一個數組,如下所示:

int[] nums = { 8, 1, 9, 4, 3, 6, 7 };

現在我們希望找出這個數組中的偶數,然後將它們降序輸出,一般我們會這麼寫:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] nums = { 8, 1, 9, 4, 3, 6, 7 };

            // 查找偶數
            List<int> list = new List<int>();
            foreach (int num in nums)
            {
                if (num % 2 == 0)
                {
                    list.Add(num);
                }
            }

            // 排序反轉
            list.Sort();
            list.Reverse();

            // 輸出偶數
            foreach (int num in list)
            {
                Console.WriteLine(num);
            }
            Console.ReadKey();
        }
    }
}

雖然能夠實現功能,但這段代碼顯得有些複雜,這個時候如果使用Linq將會非簡單,代碼如下:

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] nums = { 8, 1, 9, 4, 3, 6, 7 };
            IEnumerable<int> query = from num in nums
                                     where num % 2 == 0
                                     orderby num descending
                                     select num;
            foreach (int num in query)
            {
                Console.WriteLine(num);
            }
            Console.ReadKey();
        }
    }
}

輸出結果如下所示:

8
6
4

1、select

在查詢表達式中,select子句可以指定將在執行查詢時產生的值的類型。所有的Linq查詢語句必須以select或者group結尾。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, Name = "張三", Gender = "男", Age = 23 });
            students.Add(new Student() { Id = 2, Name = "李四", Gender = "女", Age = 27 });
            students.Add(new Student() { Id = 3, Name = "王五", Gender = "男", Age = 21 });
            students.Add(new Student() { Id = 4, Name = "趙六", Gender = "女", Age = 25 });

            IEnumerable<Student> query = from student in students
                                         select student;
            foreach (var item in query)
            {
                Console.WriteLine(item.Id + "," + item.Name + "," + item.Gender + "," + item.Age);
            }
            Console.ReadKey();
        }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }
    }
}

輸出結果如下所示:

1,張三,男,23
2,李四,女,27
3,王五,男,21
4,趙六,女,25

2、where

很多時候我們需要設置查詢條件,這時就可以使用where字句。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, Name = "張三", Gender = "男", Age = 23 });
            students.Add(new Student() { Id = 2, Name = "李四", Gender = "女", Age = 27 });
            students.Add(new Student() { Id = 3, Name = "王五", Gender = "男", Age = 21 });
            students.Add(new Student() { Id = 4, Name = "趙六", Gender = "女", Age = 25 });

            IEnumerable<Student> query = from student in students
                                         where student.Gender == "男"
                                         select student;
            foreach (var item in query)
            {
                Console.WriteLine(item.Id + "," + item.Name + "," + item.Gender + "," + item.Age);
            }
            Console.ReadKey();
        }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }
    }
}

輸出結果如下所示:

1,張三,男,23
3,王五,男,21

3、let

let可以創建一個範圍變量來存儲結果,變量被創建後,不能修改或把其他表達式的結果重新賦值給它。此範圍變量可以再後續的Linq中使用。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, Name = "張三", Gender = "男", Age = 23 });
            students.Add(new Student() { Id = 2, Name = "李四", Gender = "女", Age = 27 });
            students.Add(new Student() { Id = 3, Name = "王五", Gender = "男", Age = 21 });
            students.Add(new Student() { Id = 4, Name = "趙六", Gender = "女", Age = 25 });

            IEnumerable<Student> query = from student in students
                                         let gender = "男"
                                         let age = 22
                                         where student.Gender == gender && student.Age > age
                                         select student;
            foreach (var item in query)
            {
                Console.WriteLine(item.Id + "," + item.Name + "," + item.Gender + "," + item.Age);
            }
            Console.ReadKey();
        }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }
    }
}

輸出結果如下所示:

1,張三,男,23

4、orderby

根據字段進行排序也是常見的操作,Linq中可以使用orderby來實現排序。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, Name = "張三", Gender = "男", Age = 23 });
            students.Add(new Student() { Id = 2, Name = "李四", Gender = "女", Age = 27 });
            students.Add(new Student() { Id = 3, Name = "王五", Gender = "男", Age = 21 });
            students.Add(new Student() { Id = 4, Name = "趙六", Gender = "女", Age = 25 });

            IEnumerable<Student> query = from student in students
                                         where student.Gender == "男"
                                         orderby student.Age
                                         select student;
            foreach (var item in query)
            {
                Console.WriteLine(item.Id + "," + item.Name + "," + item.Gender + "," + item.Age);
            }
            Console.ReadKey();
        }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }
    }
}

輸出結果如下所示:

3,王五,男,21
1,張三,男,23

5、group-by

一般使用group-by實現分組查詢操作。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, Name = "張三", Gender = "男", Age = 23 });
            students.Add(new Student() { Id = 2, Name = "李四", Gender = "女", Age = 27 });
            students.Add(new Student() { Id = 3, Name = "王五", Gender = "男", Age = 21 });
            students.Add(new Student() { Id = 4, Name = "趙六", Gender = "女", Age = 25 });

            IEnumerable<IGrouping<string, Student>> query = from student in students
                                                            group student by student.Gender;
            foreach (var group in query)
            {
                Console.WriteLine(group.Key);
                foreach (var item in group)
                {
                    Console.WriteLine(item.Id + "," + item.Name + "," + item.Gender + "," + item.Age);
                }
            }
            Console.ReadKey();
        }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }
    }
}

輸出結果如下所示:

男
1,張三,男,23
3,王五,男,21
女
2,李四,女,27
4,趙六,女,25

6、group-by-into

我們也可以使用group-by-into實現分組查詢。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, Name = "張三", Gender = "男", Age = 23 });
            students.Add(new Student() { Id = 2, Name = "李四", Gender = "女", Age = 27 });
            students.Add(new Student() { Id = 3, Name = "王五", Gender = "男", Age = 21 });
            students.Add(new Student() { Id = 4, Name = "趙六", Gender = "女", Age = 25 });

            IEnumerable<IGrouping<string, Student>> query = from student in students
                                                            group student by student.Gender into groups
                                                            where groups.Key == "男"
                                                            select groups;
            foreach (var group in query)
            {
                foreach (var item in group)
                {
                    Console.WriteLine(item.Id + "," + item.Name + "," + item.Gender + "," + item.Age);
                }
            }
            Console.ReadKey();
        }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }
    }
}

輸出結果如下所示:

1,張三,男,23
3,王五,男,21

7、內連接查詢

內連接查詢就是查找兩個表中能夠匹配的數據,Linq使用join實現內連接查詢。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Class> classes = new List<Class>();
            classes.Add(new Class() { Id = 1, ClassName = "一班" });
            classes.Add(new Class() { Id = 2, ClassName = "二班" });
            classes.Add(new Class() { Id = 3, ClassName = "三班" });
            classes.Add(new Class() { Id = 4, ClassName = "四班" });

            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, StudentName = "張三", Gender = "男", Age = 23, ClassId = 1 });
            students.Add(new Student() { Id = 2, StudentName = "李四", Gender = "女", Age = 27, ClassId = 2 });
            students.Add(new Student() { Id = 3, StudentName = "王五", Gender = "男", Age = 21, ClassId = 3 });
            students.Add(new Student() { Id = 4, StudentName = "趙六", Gender = "女", Age = 25, ClassId = 5 });

            IEnumerable<Student> query = from s in students
                                         join c in classes on s.ClassId equals c.Id
                                         select s;
            foreach (var item in query)
            {
                Console.WriteLine(item.Id + "," + item.StudentName + "," + item.Gender + "," + item.Age + "," + item.ClassId);
            }
            Console.ReadKey();
        }
    }

    class Class
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名稱
        /// </summary>
        public string ClassName { get; set; }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string StudentName { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 班級編號
        /// </summary>
        public int ClassId { get; set; }
    }
}

輸出結果如下所示:

1,張三,男,23,1
2,李四,女,27,2
3,王五,男,21,3

8、組連接查詢

組連接是與分組查詢是一樣的。即根據分組得到結果。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Class> classes = new List<Class>();
            classes.Add(new Class() { Id = 1, ClassName = "一班" });
            classes.Add(new Class() { Id = 2, ClassName = "二班" });
            classes.Add(new Class() { Id = 3, ClassName = "三班" });
            classes.Add(new Class() { Id = 4, ClassName = "四班" });

            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, StudentName = "張三", Gender = "男", Age = 23, ClassId = 1 });
            students.Add(new Student() { Id = 2, StudentName = "李四", Gender = "女", Age = 27, ClassId = 2 });
            students.Add(new Student() { Id = 3, StudentName = "王五", Gender = "男", Age = 21, ClassId = 3 });
            students.Add(new Student() { Id = 4, StudentName = "趙六", Gender = "女", Age = 25, ClassId = 4 });

            var query = from c in classes
                        join s in students on c.Id equals s.ClassId into result
                        select new
                        {
                            ClassName = c.ClassName,
                            Students = result
                        };
            foreach (var obj in query)
            {
                Console.WriteLine(obj.ClassName);
                foreach (var item in obj.Students)
                {
                    Console.WriteLine(item.Id + "," + item.StudentName + "," + item.Gender + "," + item.Age);
                }
            }
            Console.ReadKey();
        }
    }

    class Class
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名稱
        /// </summary>
        public string ClassName { get; set; }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string StudentName { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 班級編號
        /// </summary>
        public int ClassId { get; set; }
    }
}

輸出結果如下所示:

一班
1,張三,男,23
二班
2,李四,女,27
三班
3,王五,男,21
四班
4,趙六,女,25

9、左連接查詢

使用左連接查詢需要注意空值的判斷,否則會引發異常。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Class> classes = new List<Class>();
            classes.Add(new Class() { Id = 1, ClassName = "一班" });
            classes.Add(new Class() { Id = 2, ClassName = "二班" });
            classes.Add(new Class() { Id = 3, ClassName = "三班" });
            classes.Add(new Class() { Id = 4, ClassName = "四班" });

            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, StudentName = "張三", Gender = "男", Age = 23, ClassId = 1 });
            students.Add(new Student() { Id = 2, StudentName = "李四", Gender = "女", Age = 27, ClassId = 2 });
            students.Add(new Student() { Id = 3, StudentName = "王五", Gender = "男", Age = 21, ClassId = 3 });
            students.Add(new Student() { Id = 4, StudentName = "趙六", Gender = "女", Age = 25, ClassId = 5 });

            var query = from c in classes
                        join s in students on c.Id equals s.ClassId into result
                        from r in result.DefaultIfEmpty()
                        select new
                        {
                            ClassName = c.ClassName,
                            StudentName = r != null ? r.StudentName : "學生姓名未知",
                            Gender = r != null ? r.Gender : "學生性別未知"
                        };
            foreach (var item in query)
            {
                Console.WriteLine(item.ClassName + "," + item.StudentName);
            }
            Console.ReadKey();
        }
    }

    class Class
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名稱
        /// </summary>
        public string ClassName { get; set; }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string StudentName { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 班級編號
        /// </summary>
        public int ClassId { get; set; }
    }
}

輸出結果如下所示:

一班,張三
二班,李四
三班,王五
四班,學生姓名未知

10、交叉連接

交叉連接很簡單,就是兩張表的逐一匹配。

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

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Class> classes = new List<Class>();
            classes.Add(new Class() { Id = 1, ClassName = "一班" });
            classes.Add(new Class() { Id = 2, ClassName = "二班" });
            classes.Add(new Class() { Id = 3, ClassName = "三班" });
            classes.Add(new Class() { Id = 4, ClassName = "四班" });

            List<Student> students = new List<Student>();
            students.Add(new Student() { Id = 1, StudentName = "張三", Gender = "男", Age = 23, ClassId = 1 });
            students.Add(new Student() { Id = 2, StudentName = "李四", Gender = "女", Age = 27, ClassId = 2 });
            students.Add(new Student() { Id = 3, StudentName = "王五", Gender = "男", Age = 21, ClassId = 3 });
            students.Add(new Student() { Id = 4, StudentName = "趙六", Gender = "女", Age = 25, ClassId = 5 });

            var query = from s in students
                        from c in classes
                        select new
                        {
                            ClassName = c.ClassName,
                            StudentName = s.StudentName,
                            Gender = s.Gender
                        };
            foreach (var item in query)
            {
                Console.WriteLine(item.ClassName + "," + item.StudentName + "," + item.Gender);
            }
            Console.ReadKey();
        }
    }

    class Class
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名稱
        /// </summary>
        public string ClassName { get; set; }
    }

    class Student
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 姓名
        /// </summary>
        public string StudentName { get; set; }

        /// <summary>
        /// 性別
        /// </summary>
        public string Gender { get; set; }

        /// <summary>
        /// 年齡
        /// </summary>
        public int Age { get; set; }

        /// <summary>
        /// 班級編號
        /// </summary>
        public int ClassId { get; set; }
    }
}

輸出結果如下所示:

一班,張三,男
二班,張三,男
三班,張三,男
四班,張三,男
一班,李四,女
二班,李四,女
三班,李四,女
四班,李四,女
一班,王五,男
二班,王五,男
三班,王五,男
四班,王五,男
一班,趙六,女
二班,趙六,女
三班,趙六,女
四班,趙六,女
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章