15-bo‘lim
LINQ
Where, Select, OrderBy, GroupBy va Aggregate, kechiktirilgan bajarish, First va FirstOrDefault farqi hamda so'rov sintaksisi.
Ushbu bo‘lim mundarijasi
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:
(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));
Aziza, Husanboy, Nodira
Endi xuddi shuni LINQ bilan:
(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));
Aziza, Husanboy, Nodira
Uchta qator, oraliq o'zgaruvchi yo'q, maqsad ko'rinib turibdi.
Asosiy metodlar #
(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 #
var alochilar = talabalar.Where(t => t.Ball >= 85);
foreach (var t in alochilar)
{
Console.WriteLine($"{t.Ism}: {t.Ball}");
}
Husanboy: 92
Nodira: 85
Aziza: 95
Select - o'zgartirish #
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));
HUSANBOY, MALIKA, NODIRA, AZIZA, KAMOLA
H.92 M.78 N.85 A.95 K.64
OrderBy - saralash #
var ballBoyicha = talabalar.OrderByDescending(t => t.Ball);
foreach (var t in ballBoyicha)
{
Console.WriteLine($"{t.Ball,3} {t.Ism}");
}
95 Aziza
92 Husanboy
85 Nodira
78 Malika
64 Kamola
Ikkinchi mezon uchun ThenBy ishlatiladi:
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}");
}
A 92 Husanboy
A 85 Nodira
A 64 Kamola
B 95 Aziza
B 78 Malika
Yig'uvchi metodlar #
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)}");
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 #
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}");
}
}
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 #
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}");
}
Birinchi 90+: Husanboy
99+ topildimi: (yo'q)
First xatosi: Sequence contains no matching element
| Metod | Topilmasa | Bir nechta topilsa |
|---|---|---|
First | Istisno | Birinchisini beradi |
FirstOrDefault | default | Birinchisini beradi |
Single | Istisno | Istisno |
SingleOrDefault | default | Istisno |
Last / LastOrDefault | Istisno / default | Oxirgisini beradi |
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:
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: 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.
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}");
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 #
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"]}");
Ro'yxat: 3 ta
Massiv: 5 ta
Nodira balli: 85
Boshqa foydali metodlar #
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)}");
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
| Metod | Nima qiladi |
|---|---|
Distinct | Takrorlarni olib tashlaydi |
Take(n) / Skip(n) | Birinchi n ta / n tasini o'tkazib |
Reverse | Teskari tartib |
Chunk(n) | n tadan bo'laklarga ajratadi |
Aggregate | Elementlarni ketma-ket birlashtiradi |
SelectMany | Ichma-ich to'plamlarni yoyadi |
Zip | Ikki to'plamni juftlaydi |
So'rov sintaksisi #
LINQ ning ikkinchi yozilish usuli - SQL ga o'xshash:
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));
Aziza (95)
Husanboy (92)
Nodira (85)
Ikkala yozuv ham bir xil ishlaydi - kompilyator so'rov sintaksisini metodlarga aylantiradi.
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.
- Talabalar ro'yxatidan 80 dan yuqori ball olganlarni
Wherebilan toping. - Faqat ismlarni
Selectbilan ajratib oling. - Ball bo'yicha kamayish tartibida saralang.
OrderByvaThenByni birga ishlating.Count,Sum,Average,Maxni sinab ko'ring.GroupBybilan guruhlarga ajratib, har birining o'rtachasini chiqaring.FirstvaFirstOrDefaultfarqini amalda ko'ring.- Kechiktirilgan bajarishni
Addmisolida takrorlang. ToList()qo'shib, farqni kuzating.- Bitta so'rovni ikkala sintaksisda yozing.
Xulosa #
- LINQ "nima kerakligini" yozish imkonini beradi, siklsiz.
Wherefiltrlaydi,Selecto'zgartiradi,OrderBysaralaydi.GroupByguruhlarga ajratadi; har guruhdaKeybo'ladi.Firsttopilmasa istisno,FirstOrDefaultdefaultqaytaradi.Singleaynan bitta natija kutilganda ishlatiladi.- LINQ so'rovlari kechiktirilgan: natija kerak bo'lgandagina hisoblanadi va har safar qayta hisoblanadi.
- Buning oldini olish uchun
ToList()yokiToArray(). - Ikki sintaksis bor; amalda metod sintaksisi ko'proq ishlatiladi.
Keyingi bo'limda delegatlar, lambda va hodisalarni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.