15-bo‘lim

LINQ

Where, Select, OrderBy, GroupBy va Aggregate, kechiktirilgan bajarish, First va FirstOrDefault farqi hamda so'rov sintaksisi.

🕑 16 daqiqa o‘qish 📄 587 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Muammo: sikl bilan yozish
  2. Asosiy metodlar
  3. Where - filtrlash
  4. Select - o'zgartirish
  5. OrderBy - saralash
  6. Yig'uvchi metodlar
  7. GroupBy - guruhlash
  8. First, Single va ularning xavfsiz variantlari
  9. Kechiktirilgan bajarish
  10. ToList va ToArray
  11. Boshqa foydali metodlar
  12. So'rov sintaksisi
  13. Xulosa

LINQ (Language Integrated Query) - to'plamlar ustida so'rov yozish vositasi. U C# ning eng ajralib turadigan imkoniyati.

LINQ bilan "nima kerakligini" yozasiz, "qanday qilishni" emas.

Muammo: sikl bilan yozish #

Talabalar ichidan 80 dan yuqori ball olganlarni topib, ism bo'yicha saralash kerak:

CSHARP
(string Ism, int Ball)[] sinf =
[
    ("Husanboy", 92),
    ("Malika", 78),
    ("Nodira", 85),
    ("Aziza", 95),
    ("Kamola", 64)
];

// sikl bilan
List<string> topilganlar = [];
foreach (var t in sinf)
{
    if (t.Ball > 80)
    {
        topilganlar.Add(t.Ism);
    }
}
topilganlar.Sort();

Console.WriteLine(string.Join(", ", topilganlar));
Natija
Aziza, Husanboy, Nodira

Endi xuddi shuni LINQ bilan:

CSHARP
(string Ism, int Ball)[] sinf =
[
    ("Husanboy", 92),
    ("Malika", 78),
    ("Nodira", 85),
    ("Aziza", 95),
    ("Kamola", 64)
];

var topilganlar = sinf
    .Where(t => t.Ball > 80)
    .OrderBy(t => t.Ism)
    .Select(t => t.Ism);

Console.WriteLine(string.Join(", ", topilganlar));
Natija
Aziza, Husanboy, Nodira

Uchta qator, oraliq o'zgaruvchi yo'q, maqsad ko'rinib turibdi.

Asosiy metodlar #

CSHARP
(string Ism, int Ball, string Guruh)[] talabalar =
[
    ("Husanboy", 92, "A"),
    ("Malika", 78, "B"),
    ("Nodira", 85, "A"),
    ("Aziza", 95, "B"),
    ("Kamola", 64, "A")
];

Yuqoridagi ma'lumot bilan ishlaymiz.

Where - filtrlash #

CSHARP
var alochilar = talabalar.Where(t => t.Ball >= 85);

foreach (var t in alochilar)
{
    Console.WriteLine($"{t.Ism}: {t.Ball}");
}
Natija
Husanboy: 92
Nodira: 85
Aziza: 95

Select - o'zgartirish #

CSHARP
var ismlar = talabalar.Select(t => t.Ism.ToUpper());
Console.WriteLine(string.Join(", ", ismlar));

var qisqa = talabalar.Select(t => $"{t.Ism[0]}.{t.Ball}");
Console.WriteLine(string.Join(" ", qisqa));
Natija
HUSANBOY, MALIKA, NODIRA, AZIZA, KAMOLA
H.92 M.78 N.85 A.95 K.64

OrderBy - saralash #

CSHARP
var ballBoyicha = talabalar.OrderByDescending(t => t.Ball);

foreach (var t in ballBoyicha)
{
    Console.WriteLine($"{t.Ball,3}  {t.Ism}");
}
Natija
 95  Aziza
 92  Husanboy
 85  Nodira
 78  Malika
 64  Kamola

Ikkinchi mezon uchun ThenBy ishlatiladi:

CSHARP
var tartib = talabalar
    .OrderBy(t => t.Guruh)
    .ThenByDescending(t => t.Ball);

foreach (var t in tartib)
{
    Console.WriteLine($"{t.Guruh}  {t.Ball,3}  {t.Ism}");
}
Natija
A   92  Husanboy
A   85  Nodira
A   64  Kamola
B   95  Aziza
B   78  Malika

Yig'uvchi metodlar #

CSHARP
Console.WriteLine($"Soni:      {talabalar.Count()}");
Console.WriteLine($"85+ soni:  {talabalar.Count(t => t.Ball >= 85)}");
Console.WriteLine($"Yig'indi:  {talabalar.Sum(t => t.Ball)}");
Console.WriteLine($"Eng yuqori:{talabalar.Max(t => t.Ball)}");
Console.WriteLine($"Eng past:  {talabalar.Min(t => t.Ball)}");
Console.WriteLine($"O'rtacha:  {talabalar.Average(t => t.Ball)}");
Console.WriteLine($"Barchasi 60+: {talabalar.All(t => t.Ball >= 60)}");
Console.WriteLine($"90+ bormi:    {talabalar.Any(t => t.Ball >= 90)}");
Natija
Soni:      5
85+ soni:  3
Yig'indi:  414
Eng yuqori:95
Eng past:  64
O'rtacha:  82.8
Barchasi 60+: True
90+ bormi:    True

GroupBy - guruhlash #

CSHARP
var guruhlar = talabalar.GroupBy(t => t.Guruh);

foreach (var guruh in guruhlar.OrderBy(g => g.Key))
{
    Console.WriteLine($"{guruh.Key} guruhi - {guruh.Count()} talaba, "
                      + $"o'rtacha {guruh.Average(t => t.Ball):F1}");

    foreach (var t in guruh.OrderByDescending(t => t.Ball))
    {
        Console.WriteLine($"    {t.Ism,-10} {t.Ball}");
    }
}
Natija
A guruhi - 3 talaba, o'rtacha 80.3
    Husanboy   92
    Nodira     85
    Kamola     64
B guruhi - 2 talaba, o'rtacha 86.5
    Aziza      95
    Malika     78

GroupBy guruhlar to'plamini qaytaradi. Har bir guruhda Key (guruhlash mezoni) va elementlar bo'ladi.

First, Single va ularning xavfsiz variantlari #

CSHARP
var birinchi = talabalar.First(t => t.Ball > 90);
Console.WriteLine($"Birinchi 90+: {birinchi.Ism}");

var yoq = talabalar.FirstOrDefault(t => t.Ball > 99);
Console.WriteLine($"99+ topildimi: {yoq.Ism ?? "(yo'q)"}");

try
{
    var xato = talabalar.First(t => t.Ball > 99);
}
catch (InvalidOperationException x)
{
    Console.WriteLine($"First xatosi: {x.Message}");
}
Natija
Birinchi 90+: Husanboy
99+ topildimi: (yo'q)
First xatosi: Sequence contains no matching element
MetodTopilmasaBir nechta topilsa
FirstIstisnoBirinchisini beradi
FirstOrDefaultdefaultBirinchisini beradi
SingleIstisnoIstisno
SingleOrDefaultdefaultIstisno
Last / LastOrDefaultIstisno / defaultOxirgisini beradi
Qaysi birini tanlash
  • First - "kamida bittasi bor" deb bilsangiz;
  • FirstOrDefault - bo'lmasligi ham mumkin;
  • Single - "aynan bittasi bo'lishi kerak" degan qoida bo'lsa (masalan ID bo'yicha qidirish).

Single ning foydasi shunda: agar ma'lumotda ikkita bir xil ID paydo bo'lsa, u darhol xato beradi va siz muammoni bilib olasiz.

Kechiktirilgan bajarish #

Bu LINQ ning eng muhim va eng ko'p chalkashtiriladigan xususiyati:

CSHARP
List<int> sonlar = [1, 2, 3];

var sorov = sonlar.Where(s => s > 1);

sonlar.Add(4);

Console.WriteLine($"Natija: {string.Join(", ", sorov)}");
Console.WriteLine($"Elementlar soni: {sorov.Count()}");
Natija
Natija: 2, 3, 4
Elementlar soni: 3

sorov e'lon qilinganda hech narsa hisoblanmadi. Hisoblash faqat natija kerak bo'lganda - string.Join chaqirilganda - boshlandi. Shu sababli keyin qo'shilgan 4 ham natijaga tushdi.

Bu kutilmagan xatolarga olib kelishi mumkin
CSHARP
List<int> sonlar = [1, 2, 3];
var sorov = sonlar.Where(s =>
{
    Console.WriteLine($"  tekshirilmoqda {s}");
    return s > 1;
});

Console.WriteLine("Birinchi marta:");
int a = sorov.Count();

Console.WriteLine("Ikkinchi marta:");
int b = sorov.Count();

Console.WriteLine($"{a} va {b}");
Natija
Birinchi marta:
  tekshirilmoqda 1
  tekshirilmoqda 2
  tekshirilmoqda 3
Ikkinchi marta:
  tekshirilmoqda 1
  tekshirilmoqda 2
  tekshirilmoqda 3
2 va 2

So'rov ikki marta bajarildi. Agar u bazaga murojaat qilayotgan bo'lsa, ikkita so'rov ketadi.

Yechim: natijani moddiylashtiring - ToList() yoki ToArray() chaqiring. Shundan keyin u oddiy ro'yxatga aylanadi va qayta hisoblanmaydi.

ToList va ToArray #

CSHARP
var royxat = talabalar.Where(t => t.Ball > 80).ToList();
var massiv = talabalar.Select(t => t.Ism).ToArray();
var lugat = talabalar.ToDictionary(t => t.Ism, t => t.Ball);

Console.WriteLine($"Ro'yxat: {royxat.Count} ta");
Console.WriteLine($"Massiv:  {massiv.Length} ta");
Console.WriteLine($"Nodira balli: {lugat["Nodira"]}");
Natija
Ro'yxat: 3 ta
Massiv:  5 ta
Nodira balli: 85

Boshqa foydali metodlar #

CSHARP
int[] sonlar = [5, 3, 8, 3, 1, 8, 9];

Console.WriteLine($"Takrorsiz:   {string.Join(", ", sonlar.Distinct())}");
Console.WriteLine($"Birinchi 3:  {string.Join(", ", sonlar.Take(3))}");
Console.WriteLine($"3 tasin o'tkazib: {string.Join(", ", sonlar.Skip(3))}");
Console.WriteLine($"Teskari:     {string.Join(", ", sonlar.Reverse())}");
Console.WriteLine($"Eng kattasi: {sonlar.Max()}");
Console.WriteLine($"Yig'indisi:  {sonlar.Aggregate((a, b) => a + b)}");
Console.WriteLine($"Ko'paytma:   {sonlar.Aggregate((a, b) => a * b)}");
Natija
Takrorsiz:   5, 3, 8, 1, 9
Birinchi 3:  5, 3, 8
3 tasin o'tkazib: 3, 1, 8, 9
Teskari:     9, 8, 1, 3, 8, 3, 5
Eng kattasi: 9
Yig'indisi:  37
Ko'paytma:   25920
MetodNima qiladi
DistinctTakrorlarni olib tashlaydi
Take(n) / Skip(n)Birinchi n ta / n tasini o'tkazib
ReverseTeskari tartib
Chunk(n)n tadan bo'laklarga ajratadi
AggregateElementlarni ketma-ket birlashtiradi
SelectManyIchma-ich to'plamlarni yoyadi
ZipIkki to'plamni juftlaydi

So'rov sintaksisi #

LINQ ning ikkinchi yozilish usuli - SQL ga o'xshash:

CSHARP
var natija =
    from t in talabalar
    where t.Ball > 80
    orderby t.Ball descending
    select $"{t.Ism} ({t.Ball})";

Console.WriteLine(string.Join("\n", natija));
Natija
Aziza (95)
Husanboy (92)
Nodira (85)

Ikkala yozuv ham bir xil ishlaydi - kompilyator so'rov sintaksisini metodlarga aylantiradi.

Qaysi yozuvni tanlash

Amalda metod sintaksisi (.Where().Select()) ancha ko'p ishlatiladi, chunki barcha metodlar unda mavjud - so'rov sintaksisida esa faqat bir qismi bor.

So'rov sintaksisi murakkab birlashtirishlarda (join, group by) o'qish osonroq bo'lishi mumkin.

Bitta faylda ikkalasini aralashtirmang - bitta uslubni tanlang.

Amaliy topshiriq
  1. Talabalar ro'yxatidan 80 dan yuqori ball olganlarni Where bilan toping.
  2. Faqat ismlarni Select bilan ajratib oling.
  3. Ball bo'yicha kamayish tartibida saralang.
  4. OrderBy va ThenBy ni birga ishlating.
  5. Count, Sum, Average, Max ni sinab ko'ring.
  6. GroupBy bilan guruhlarga ajratib, har birining o'rtachasini chiqaring.
  7. First va FirstOrDefault farqini amalda ko'ring.
  8. Kechiktirilgan bajarishni Add misolida takrorlang.
  9. ToList() qo'shib, farqni kuzating.
  10. Bitta so'rovni ikkala sintaksisda yozing.

Xulosa #

  • LINQ "nima kerakligini" yozish imkonini beradi, siklsiz.
  • Where filtrlaydi, Select o'zgartiradi, OrderBy saralaydi.
  • GroupBy guruhlarga ajratadi; har guruhda Key bo'ladi.
  • First topilmasa istisno, FirstOrDefault default qaytaradi.
  • Single aynan bitta natija kutilganda ishlatiladi.
  • LINQ so'rovlari kechiktirilgan: natija kerak bo'lgandagina hisoblanadi va har safar qayta hisoblanadi.
  • Buning oldini olish uchun ToList() yoki ToArray().
  • Ikki sintaksis bor; amalda metod sintaksisi ko'proq ishlatiladi.

Keyingi bo'limda delegatlar, lambda va hodisalarni o'rganamiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.