Lekce 11 - LINQ - Restrikční, Projekční operátory a Rozdělující operace
V předchozím kvízu, Kvíz - Slovníky, množiny, fronta, zásobník ve VB.NET Kolekce, jsme si ověřili nabyté zkušenosti z předchozích lekcí.
V dnešním LINQ tutoriálu pro VB.NET si popíšeme další operátory, které můžeme používat. Budou to operátory restrikční a projekční, a také rozdělující operace.
Restrikční operátory
Výsledek dotazu můžeme nějak podmínit a vybrat tedy jen data, která
splňují nějakou podmínku. Mezi restrikční operátory
patří nám již známé where
.
where
Operátor where
umožňuje vybrat jen ta data, která splňují
určitou podmínku.
Z posloupnosti čísel vybereme tak, která jsou větší
než 5
:
Dim cisla1 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim dotaz1 = From c In cisla1 Where (c > 5) Select c For Each c As Integer In dotaz1 Console.WriteLine(c) Next
Dotaz vybere:
Konzolová aplikace
8
9
Indexované Where()
Co jsme si ještě neukazovali je použití tzv. indexovaného
Where()
, ve kterém můžeme pracovat s indexem
prvku v kolekci. Vyberme čísla, která mají stejnou
hodnotu jako jejich index v poli:
Dim cisla2 As Integer() = {0, 5, 2, 5, 4, 1, 3, 7} Dim dotaz2 As Object = cisla2.Where(Function(cislo, index) cislo = index) For Each c As Integer In dotaz2 Console.WriteLine(c) Next
Dotaz vybere:
Konzolová aplikace
0
2
4
7
Použili jsme zde zápis dotazu přes metody. Některé operátory jinak zapsat nelze a nepodporují SQL-like zápis. Budeme se tu s nimi setkávat i nadále.
Projekční operátory
S vybranými prvky se nemusíme spokojit tak, jak jsou, ale můžeme z výsledných prvků vybrat pouze nějakou vlastnost.
select
Pomocí select
určíme co konkrétně nás u vybraných prvků
zajímá. Nechme si vrátit dvojnásobky čísel větších
než 5
:
Dim cisla3 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim dotaz3 As Object = From c In cisla3 Where (c > 5) Select c * 2 For Each c As Integer In dotaz3 Console.WriteLine(c) Next
Dotaz vybere:
Konzolová aplikace
16
18
Stejně tak můžeme mapovat i nějakou vlastnost nebo výsledek metody,
např. Length
nebo ToLower()
na řetězci:
Dim slova As String() = {"SOcialNi", "SiT", "ITnetWOrk"} Dim dotaz = From s In slova Select s.ToLower() For Each s As String In dotaz Console.WriteLine(s) Next
Dotaz vybere:
Konzolová aplikace
socialni
sit
itnetwork
Indexovaný Select()
s anonymními typy
Stejně jako Where()
i u operátoru Select()
máme
přístup k indexu prvku. S anonymními
typy jsme se již seznámili.
Ukažme si tedy, jak vybrat anonymní typ, obsahující pozici a hodnotu daného prvku:
Dim cisla5 As Integer() = {3, 5, 8, 5} Dim dotaz5 = cisla5.[Select](Function(cislo, index) New With {.Index = index, .Hodnota = cislo}) For Each d As Object In dotaz5 Console.WriteLine(d) Next
Dotaz vybere:
Konzolová aplikace
{ Index = 0, Hodnota = 3 }
{ Index = 1, Hodnota = 5 }
{ Index = 2, Hodnota = 8 }
{ Index = 3, Hodnota = 5 }
Rozdělující operace
Původní kolekci můžeme nějakým způsobem rozdělit a dále pracovat pouze s její částí.
Take()
Take()
vybere prvních několik prvků z
kolekce a zbytek zahodí. Vyberme si pouze první tři čísla
z pole:
Dim cisla6 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim dotaz6 = cisla6.Take(3) For Each d As Object In dotaz6 Console.WriteLine(d) Next
Dotaz vybere:
Konzolová aplikace
3
5
8
Take()
s dotazem
Take()
můžeme zavolat i na výsledku LINQ
dotazu tak, že ho ozávorkujeme:
Dim cisla7 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim dotaz7 = (From c In cisla7 Where c > 3 Select c * 2).Take(3) For Each d As Object In dotaz7 Console.WriteLine(d) Next
Dotaz vybere:
Konzolová aplikace
10
16
10
Skip()
Skip()
je opačná funkce k Take()
. Vybere tedy
všechny prvky kromě několika prvních, které
přeskočí.
Vyberme z pole všechna čísla kromě pěti prvních:
Dim cisla8 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim dotaz8 = cisla8.Skip(5) For Each d As Object In dotaz8 Console.WriteLine(d) Next
Dotaz vybere:
Konzolová aplikace
1
3
4
Pomocí Skip()
a Take()
se často řeší výběr
náhodného prvku:
Dim cisla9 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim r As New Random(Now.Millisecond) ' inicializace random s "náhodnou" hodnotou ' pokud neuvedeme, pak dotaz bude vracet stejný prvek Dim dotaz9 As Object = cisla9.Skip(r.[Next](cisla9.Length)).Take(1) For Each d As Integer In dotaz9 Console.WriteLine(d) Next
Dotaz vybere jedno náhodné číslo z pole.
TakeWhile()
Prvky můžeme vybírat postupně od začátku až do splnění určité podmínky. Od té chvíle se přidávání prvků do výsledku zastaví.
Vyberme si prvních několik čísel, které jsou větší
než 2
:
Dim cisla10 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim dotaz10 = cisla10.TakeWhile(Function(c) c > 2) For Each d As Integer In dotaz10 Console.WriteLine(d) Next
Dotaz vybere:
Konzolová aplikace
3
5
8
5
9
TakeWhile()
můžeme také indexovat.
SkipWhile()
Analogicky existuje i SkipWhile()
, které by čísla
přeskakovalo dokud platí určitá podmínka
a až poté začne čísla do výsledku přidávat.
Přeskočme prvních několik čísel, která jsou větší
než 2
:
Dim cisla11 As Integer() = {3, 5, 8, 5, 9, 1, 3, 4} Dim dotaz11 = cisla11.SkipWhile(Function(c) c > 2) For Each d As Integer In dotaz11 Console.WriteLine(d) Next
Dotaz vybere:
Konzolová aplikace
1
3
4
SkipWhile()
můžeme rovněž indexovat.
Skip()
můžeme (jako každou podobnou metodu)
zavolat jako u příkladu s Take()
na dotazu tak, že ho
ozávorkujeme. Toto již nebudu u dalších metod uvádět.
V příští lekci, LINQ - Řadicí a Množinové operátory ve VB.NET, budeme pokračovat v popisu syntaxe LINQ operátorů. Budou to operátory řadicí a množinové.