IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

9. diel - LINQ operátory 1

V predchádzajúcom kvíze, Kvíz - Slovníky, množiny, front, zásobník v C# .NET Kolekcia, sme si overili nadobudnuté skúsenosti z predchádzajúcich lekcií.

So základnou syntaxou LINQ dotazov sme už oboznámení. V niekoľkých lekciách si teraz popíšme čo všetko nám LINQ ponúka, teda metódy, presnejšie povedané operátory, ktoré môžete vo svojich dotazoch používať. Všetko si ukážeme na príkladoch. Prvých niekoľko príkladov bude opakovaním, s ďalšími nadobudne práca s LINQ nových rozmerov.

Reštrikčné operátory

Výsledok dotazu môžeme nejako podmieniť a vybrať teda len dáta, ktoré spĺňajú nejakú podmienku. Medzi reštrikčné operátory patrí nám už známe where.

where

Operátor where umožňuje vybrať len tie dáta, ktoré spĺňajú určitú podmienku. Z postupnosti čísel vyberieme tak, ktoré sú väčšie ako 5:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = from n in numbers
            where (n > 5)
            select n;

foreach (int number in query)
    Console.WriteLine(number);

Dotaz vyberie:

Konzolová aplikácia
8
9

Všetky ďalšie príklady budú obsahovať rovnaký kód pre výpis výsledku, v článku ho už znova uvádzať nebudeme.

Indexované Where()

Čo sme si ešte neukazovali je použitie tzv. indexovaného Where(), v ktorom môžeme pracovať s indexom prvku v kolekcii. Vyberme čísla, ktoré majú rovnakú hodnotu ako ich index v poli:

int[] numbers = { 0, 5, 2, 5, 4, 1, 3, 7 };

var query = numbers.Where((number, index) => number == index);

Dotaz vyberie:

Konzolová aplikácia
0
2
4
7

Použili sme tu mimochodom zápis dotazu cez metódy. Niektoré operátory inak zapísať nemožno a nepodporujú SQL-like zápis, budeme sa tu s nimi stretávať aj naďalej.

Projekčné operátory

S vybranými prvkami sa nemusíme uspokojiť tak, ako sú, ale môžeme z výsledných prvkov vybrať iba nejakú vlastnosť.

select

Pomocou select určíme čo konkrétne nás pri vybraných prvkoch zaujíma. Nechajme si vrátiť dvojnásobky čísel väčších ako 5:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = from n in numbers
            where (n > 5)
            select n * 2;

Dotaz vrátí:

Konzolová aplikácia
16
18

Rovnako tak môžeme mapovať aj nejakú vlastnosť alebo výsledok metódy, napr. Length alebo ToLower() na reťazci:

string[] words = { "SOcial", "nEtwork", "ICTdemy" };

var query = from w in words
            select w.ToLower();

Otázka vyberie:

Konzolová aplikácia
social
network
ictdemy

Indexovaný Select() s anonymnými typmi

Rovnako ako Where() aj u operátora Select() máme prístup k indexu prvku. S anonymnými typmi sme sa zoznámili v minulej lekcii, ukážme si teda, ako vybrať anonymný typ, obsahujúci pozíciu a hodnotu daného prvku:

int[] numbers = { 3, 5, 8, 5 };

var query = numbers.Select((number, index) => new { Index = index, Value = number });

Dotaz vyberie:

Konzolová aplikácia
{ Index = 0, Value = 3 }
{ Index = 1, Value = 5 }
{ Index = 2, Value = 8 }
{ Index = 3, Value = 5 }

Rozdeľujúce operácie

Pôvodnú kolekciu môžeme nejakým spôsobom rozdeliť a ďalej pracovať iba s jej časťou.

Take()

Take() vyberie prvých niekoľko prvkov z kolekcie a zvyšok zahodí. Vyberme si iba prvé tri čísla z poľa:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.Take(3);

Dotaz vyberie:

Konzolová aplikácia
3
5
8

Take() s dotazom

Take() môžeme zavolať aj na výsledku LINQ dotazu tak, že ho ozátvoríme:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = (from n in numbers
             where (n > 3)
             select n * 2).Take(3);

Dotaz vyberie:

Konzolová aplikácia
10
16
10

Skip()

Skip() je opačná funkcia k Take(), vyberie teda všetky prvky okrem niekoľkých prvých, ktoré preskočia, od toho názov operátora.

Vyberme z poľa všetky čísla okrem prvých piatich:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.Skip(5);

Dotaz vyberie:

Konzolová aplikácia
1
3
4

Pomocou Skip() a Take() sa často rieši výber náhodného prvku:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };
Random r = new Random();

var query = numbers.Skip(r.Next(numbers.Length)).Take(1);

Dotaz vyberie jedno náhodné číslo z poľa.

Pri spustení online sa výsledok uloží do medzipamäte a bude to vyzerať, že padá stále to isté číslo. Obnovenie vyrovnávacej pamäte môžete vykonať zmenou zdrojového kódu, napr. pridaním nejakého komentára.

TakeWhile()

Prvky môžeme vyberať postupne od začiatku až do splnenia určitej podmienky. Od tej chvíle pridávanie prvkov do výsledku ustane. Vyberme si prvých niekoľko čísel, ktoré sú väčšie ako 2:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.TakeWhile(n => n > 2);

Dotaz vyberie:

Konzolová aplikácia
3
5
8
5
9

TakeWhile() môžeme tiež indexovať.

SkipWhile()

Analogicky existuje aj SkipWhile(), ktoré by čísla preskakovalo pokiaľ platí určitá podmienka a až potom začne čísla do výsledku pridávať. Preskočme prvých niekoľko čísel, ktoré sú väčšie ako 2:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.SkipWhile(n => n > 2);

Dotaz vyberie:

Konzolová aplikácia
1
3
4

SkipWhile() môžeme tiež indexovať.

Skip() môžeme (ako každú podobnú metódu) zavolať ako pri príklade s Take() na dotaze tak, že ho ozátvoríme. Toto už nebudem u ďalších metód uvádzať.

Radiace operátory

S OrderBy(), OrderByDescending(), ThenBy() a ThenByDescending() sme sa už stretli. Ukážme si ale, ako môžeme radiť pomocou Comparera.

OrderBy() pomocou IComparer

Použitie comparerov získava svoju výhodu vo chvíli, keď chceme dotaz parametrizovať a striedať kritériá, podľa ktorých triedime (necháme ich výber napr. na užívateľovi). Najprv je dôležité deklarovať si svoj comparer, v ukážke použijeme comparer textových reťazcov, ktorý porovnáva reťazce s ohľadom na veľké a malé písmená:

public class CaseSensitiveComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        return string.Compare(x, y, StringComparison.Ordinal);
    }
}

Teraz comparer vložíme do dotazu:

string[] words = { "Argentina", "anaconda", "aLbert", "Buffalo", "business", "BOmb" };

var query = words.OrderBy(w => w, new CaseSensitiveComparer());
public class CaseSensitiveComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        return string.Compare(x, y, StringComparison.Ordinal);
    }
}

Dotaz vyberie:

Konzolová aplikácia
Argentina
BOmb
Buffalo
aLbert
anaconda
business

Množinové operátory

Na kolekciu môžeme pozerať ako na množinu a použiť nasledujúce operátory, ktoré nám často zjednodušia prácu.

Distinct()

Distinct() odstráni duplicitné prvky a vráti jedinečné hodnoty v poradí, v ktorom sa prvýkrát objavili v pôvodnom poli:

int[] numbers = { 3, 5, 8, 5, 9, 1, 3, 4 };

var query = numbers.Distinct();

Dotaz vyberie:

Konzolová aplikácia
3
5
8
9
1
4

Union()

Union() vyberie množinové zjednotenie. Na vstupe sú teda dve kolekcie a na výstupe množina (kolekcia) obsahujúca všetky prvky dvoch vstupných kolekcií tak, že je každý obsiahnutý iba raz. Skúsme si to:

int[] set1 = { 3, 5, 8, 5, 9, 1, 3, 4 };
int[] set2 = { 3, 7, 2, 1, 4 };

var query = set1.Union(set2);

Dotaz vyberie:

Konzolová aplikácia
3
5
8
9
1
4
7
2

Intersect()

Intersect() vyberie množinový prienik. Na vstupe sú teda dve kolekcie a na výstupe množina (kolekcia) obsahujúca iba prvky, ktoré sú obom vstupným kolekciám spoločné. Skúsme si to:

int[] set1 = { 3, 5, 8, 5, 9, 1, 3, 4 };
int[] set2 = { 3, 7, 2, 1, 4 };

var query = set1.Intersect(set2);

Dotaz vyberie:

Konzolová aplikácia
3
1
4

Except()

Metóda Except() nám umožňuje vytvoriť postupnosť obsahujúcu tie hodnoty z prvej množiny, ktoré sa nevyskytujú v množine druhej:

int[] set1 = { 3, 5, 8, 5, 9, 1, 3, 4 };
int[] set2 = { 3, 7, 2, 1, 4 };

var query = set1.Except(set2);

Dotaz vyberie:

Konzolová aplikácia
5
8
9

V nasledujúcom cvičení, Riešené úlohy k 7.-9. lekcii práce s kolekciami v C# .NET, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Predchádzajúci článok
Kvíz - Slovníky, množiny, front, zásobník v C# .NET Kolekcia
Všetky články v sekcii
Kolekcia a LINQ v C# .NET
Preskočiť článok
(neodporúčame)
Riešené úlohy k 7.-9. lekcii práce s kolekciami v C# .NET
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
1 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity