اپراتور های Filtering در LINQ

21 فروردین 1398
درسنامه درس 4 از سری آموزش LINQ
LINQ-filtering-operators

با سلام خدمت کاربران عزیز در این بخش قصد داریم با Filtering Operator (اپراتور های فیلتر) در LINQ آشنا شویم و مثال های متعددی از آن را بررسی کنیم.

Filtering Operator چیست؟

در زبان C# برای فیلتر کردن اطلاعات خروجی از Filtering Operator (اپراتور های فیلتر) استفاده می شود.

در LINQ دو نوع متد فیلتر وجود دارد که به شرح زیر می باشند:

کاربرد نام متد
از این متد برای انتخاب مقادیری از لیست بر اساس شرایط اعمال شده استفاده می شود Where
از این متد برای استخراج نوع داده ای مشخص از لیست استفاده می شود OfType

کاربرد متد Where

فیلتر Where مشخص می کند که اطلاعات استخراج شده از منبع داده دارای چه شرطی باشند. بدین صورت که اطلاعات دریافتی باید در شرط موجود در متد where صدق کنند تا فیلتر اجازه ی عبور آن را صادر کند که کارکرد آن دقیقا مانند Where در زبان SQL است.

الگوی کلی استفاده از Where به صورت زیر می باشد:

IEnumerable<string> result = countries.Where(x => x.StartsWith("A"));

برای آشنایی با کاربرد این متد به مثال های زیر توجه کنید:

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

namespace Linqtutorials
{
    class MainClass
    {
        static void Main(string[] args)
        {

            string[] countries = { "India", "Iran", "USA", "Argentina", "Peru", "China" };
            IEnumerable<string> result = countries.Where(s => s.StartsWith("I"));
            foreach (string item in result)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }
    }
}

در این مثال یک آرایه string که در بردارنده ی نام کشور ها است ایجاد و در ادامه با استفاده از Where برای استخراج داده از آن، شرطی در نظر گرفته شده که فقط اعضایی انتخاب می شوند که اول نام آن ها I باشد. سپس این اعداد در متغیر result ذخیره می شوند.

طبق روال قبل این مثال را با روش Query بازنویسی می کنیم که لازم است عبارت جلوی result را به صورت زیر تغییر دهید:

IEnumerable<string> result = from x in countries
where x.StartsWith("A")
select x;

مثال اول قسمت قبل را در نظر بگیرید که با استفاده از متد select نام دانشجو و معدل آن را از لیست خارج و در خروجی چاپ کردیم، حالا قصد داریم فقط نام دانشجوهایی که معدل آن ها بالا تر از 15 است در خروجی نشان دهیم برای این منظور کد را به صورت زیر تغییر می دهیم:

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

namespace Linqtutorials
{
    class MainClass
    {
        static void Main(string[] args)
        {
            List<Student> stuList = new List<Student>()
            {
                new Student(){ ID=100,Name="amir",Age=23,Average=16.25},
                new Student(){ ID=101,Name="reza",Age=22,Average=12.3},
                new Student(){ ID=102,Name="sara",Age=22,Average=12},
                new Student(){ ID=103,Name="hassan",Age=24,Average=18},
                new Student(){ ID=104,Name="mina",Age=21,Average=17.11},
            };
            var StudentList = stuList.Where(x =>x.Average>15);
            Console.WriteLine("name" + "\t" + "average");
            foreach (Student item in StudentList)
            {
                Console.WriteLine("{0}" + "\t" + "{1}", item.Name, item.Average);
            }
            Console.ReadKey();
        }
    }
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public double Average { get; set; }
    }
}

کد را اجرا و خروجی آن را مشاهده کنید و دقت کنید فقط رکوردهایی که معدل آن ها بالای 15 بوده در خروجی نشان داده شده اند. به عبارت Lambda نوشته شده در where توجه کنید. متغیر x از نوع کلاس Student و خروجی آن از نوع bool است. با هدایت موس بر روی where به راحتی می توانید از صحت این موضوع مطمئن شوید.

برای بازنویسی به صورت Query، کد را به این شکل تغییر می دهیم:

var StudentList = from stu in stuList
where stu.Average > 15
select stu;

همان طور که تا اینجا متوجه شدید نوشتن کد به صورت Query ساده تر بوده و تا حدودی شبیه به کدهای SQL است، اما همیشه اینطور نخواهد بود و ممکن است در برنامه های بزرگتر روش Query کمی پیچیده و مشکل به نظر برسد که در آموزش های آینده شاهد این موضوع خواهیم بود.

خروجی مثال دوم- کاربرد Where
خروجی مثال دوم - کاربرد Where

سوال: آیا می توان در LINQ از شروط چندگانه استفاده کرد؟

جواب: بله. LINQ از شروط چندگانه پشتیبانی می کند و این عملیات به راحتی قابل پیاده سازی است.

به مثال زیر توجه کنید:

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

namespace Linqtutorials
{
    class MainClass
    {
        static void Main(string[] args)
        {

            string[] countries = { "India", "Iran", "USA", "Argentina", "Peru", "China" };
           IEnumerable<string> result = countries.Where(s => s.StartsWith("I") & s.EndsWith("n"));
            foreach (string item in result)
            {
                Console.WriteLine(item);
            }
            Console.ReadKey();
        }
    }
}

در اینجا تعین کرده ایم که فقط نام کشور هایی در خروجی نمایش داده شود که شروع با I و پایان آنها با n (کوچک) باشد. توجه داشته باشید که متدهای استفاده شده در where به کوچک و بزرگ بودن حروف حساس هستد. کد را اجرا و خروجی را مشاهده کنید.

بازنویسی این مثال به روش query به صورت زیر است:

 IEnumerable<string> result = from x in countries
where x.StartsWith("I")
where x.EndsWith("n")
select x;

کاربرد متد OfType

با استفاده از این متد می توان نوع مشخصی از داده را از منبع اطلاعاتی واکشی کنیم، به طوری که بقیه ی عناصر نادیده گرفته شوند.

الگوی استفاده از آن به صورت زیر می باشد:

IEnumerable<string> result = obj.OfType<string>();

توجه کنید که نوع داده ای که قرار است آن را استخراج کنید باید در <> قرار گیرد.

برای آشنایی با این متد به مثال های زیر توجه کنید:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Linqtutorials
{
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList obj = new ArrayList();
            obj.Add("Iran");
            obj.Add("USA");   
            obj.Add(1);
            obj.Add(true);
            obj.Add(55.6);
            obj.Add("UK");
            obj.Add("India");
            IEnumerable<string> result = obj.OfType<string>();
            foreach (var item in result)
            {
              Console.WriteLine(item);
            }
            Console.ReadLine();
       }
    }
}

در این مثال یک ArrayList تعریف شده که هر نوع داده ای را می توان در آن وارد کرد. حالتی را در نظر بگیرید که فقط به نوع مشخصی از داده های داخل یک منبع نیاز داریم، مثلا نوع string.

برای این منظور متد OfType در LINQ معرفی شده است. در این مثال نوع های مختلفی از داده در ArrayList وارد شده اند و ما قصد داریم اعضایی را که نوع آن ها string است، استخراج کنیم.

برای نوشتن با روش Query کد به این صورت تغییر می کند:

 IEnumerable result = from x in obj.OfType<int>()
select x;

خروجی در حالت انتخاب نوع داده ی string به شکل زیر است:

خروجی مثال چهارم-کاربرد OfType
خروجی مثال چهارم - کاربرد OfType

مثال جالب زیر را در نظر بگیرید:

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

namespace Linqtutorials
{
    class MainClass
    {
        static void Main(string[] args)
        {
            ArrayList persons = new ArrayList()
            {
                new Student(){ ID=100,Name="amir",Age=23,Average=16.25},
                new Student(){ ID=101,Name="reza",Age=22,Average=12.3},
                new Student(){ ID=102,Name="sara",Age=22,Average=12},
                new Student(){ ID=103,Name="hassan",Age=24,Average=18},
                new Student(){ ID=104,Name="mina",Age=21,Average=17.11},
                new Employee(){ ID=2000,Name="nader" ,Gender="Male",HoursWorked=150},
                new Employee(){ ID=2000,Name="javad" ,Gender="Male",HoursWorked=177},
                new Employee(){ ID=2000,Name="neda" ,Gender="Female",HoursWorked=110},
                new Employee(){ ID=2000,Name="arash" ,Gender="Male",HoursWorked=300},
                new Employee(){ ID=2000,Name="zahra" ,Gender="Female",HoursWorked=160},
                new Employee(){ ID=2000,Name="amin" ,Gender="Male",HoursWorked=100}
            };
            IEnumerable<Employee> personsList = persons.OfType<Employee>().Where(x => x.HoursWorked>140 & x.Gender.Equals("Female"));
            foreach (Employee item in personsList)
            {
                Console.WriteLine("{0}" + "\t" + "{1}"+"\t"+"{2}", item.Name, item.Gender,item.HoursWorked);
            }
            Console.ReadKey();
        }
    }
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public double Average { get; set; }
    }
    public class Employee
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Gender { get; set; }
        public int HoursWorked { get; set; }
    }
}

در این مثال دو کلاس Student و Employee تعریف شده که هر کدام دارای فیلد های مشخصی هستد. در کلاس Main یک ArrayList تعریف شده و درون آن با اشیای هر دو کلاس پر شده است. هدف اول ما در این مثال استخراج داده هایی از جنس کلاس Employee است که با استفاده از متد OfType قابل انجام است. حال قصد داریم فقط کارمندانی که ساعات کاری آن ها بیشتر از 140 ساعت و جنیست آن ها زن است را در خروجی نمایش دهیم که این کار با استفاده شرط داخل Where قابل پیاده سازی است.

خروجی مثال بالا به صورت زیر است:

zahra   Female  160

تمرین: مانند جلسه ی قبل سعی کنید این مثال را با استفاده از روش Query بنویسید و خروجی را با خروجی روش اول مقایسه کنید. بدیهی است که خروجی باید یکسان باشند.

جواب تمرین:

IEnumerable<Employee> personsList = from person in persons.OfType<Employee>()
where person.HoursWorked > 140
where person.Gender.Equals("Female")
select person;

این بخش از آموزش هم به پایان رسید.

موفق باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش LINQ توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.