Kezdőoldal > .NET, C#, Linq > Bevezetés a LINQ világába–(4. rész)

Bevezetés a LINQ világába–(4. rész)

2011. június 10. péntek Hozzászólás Go to comments

Az alábbi fejezetek a “Bevezetés a LINQ világába” c. irományomból valóak. Ez egy saját kis jegyzet, reményeim szerint hasznát tudjátok venni. Amiben viszont én kérném a segítségeteket az az, hogy az írást javítsátok. Ha fogalmazási, stilisztikai vagy esetleg tartalmi hibát vélnétek felfedezni kérlek írjátok meg a kommentek között.
Segítségetek előre is köszönöm.

Linq To Object összetettebb metódusai

Az előzőekben már megismerkedtünk a Linq alapjaival. Itt az ideje megismerni a LINQ által nyújtott számtalan bővítő metódussal, ami könnyebbé és gyorsabbá teszik a fejlesztést és annak menetét. Ezek a bővítő metódusok, mind a System.Linq névtérben találhatók. Ezt a névteret a Visual Studio 2008 minden projectbe beteszi, ahol nagy valószínűséggel szükség lesz rá. (Pl: Console Application, Windows Forms stb)

A következő 2 részben a Linq speciális bővítő metódusaival fogunk megismerkedni. De ne gondoljuk azt, hogy ezek a bővítő metódusok csak Linq To Objectnél használhatók. Nagy részük ugyanúgy használható lesz Linq To Sql-nél vagy más Linq Providereknél is.

Ebben a tutorialban is az előzőekben megismert és létrehozott Person gyűjteményét vesszük alapul, a legtöbb feladatnál!

Set Operators

Halmaz műveleteket tudunk a segítségükkel elvégezni a gyűjteményeken és az adatainkon.

A Distinct segítségével, az adott halmazban ismétlődő elemeket csak egyszer szedjük ki. Tehát nem engedélyezzük az elemek duplikációját. Például, ha egy listában többször fordul elő a „Budapest” név akkor, azaz eredmény halmazban csak egyszer jelenik meg.

var res = (from c in persons

          select c.City).Distinct();

var res = persons.Select(c => c.City).Distinct();

Mint látható ennek a bővítő metódusnak sincs Query Expressionos formája. Abban az esetben is sima bővítő metódusként funkcionál.

A Linq nyújt számunkra számos halmaz műveleti operátort is. A következő 3 ilyen metódust nézzük meg. Mégpedig az Unio-t (Union) Metszetet (Intersect) illetve a különbséget (Except)

Mielőtt belekezdenénk, hozzunk létre egy egyszerű int tömböt, amin dolgozni fogunk.

int[] halmaz1 = new int[] { 1, 2, 3 };

int[] halmaz2 = new int[] { 3, 4, 5 };

Unionnal két halmaz közös részét csak egyszer veszi. Azaz azok az elemek, amik az első illetve a második halmazban is szerepelnek csak egyszer fognak szerepelni az eredmény halmazban.

var union = halmaz1.Union(halmaz2);

Ebben az esetben az eredmény az: 1,2,3,4,5. Azaz a 3-as csak egyszer fordul elő.

Metszet (Intersect) képzésnél, eredményhalmazunkban azok az elemek fognak szerepelni, amelyek minden kiinduló halmazban szerepeltek.

var intersect = halmaz1.Intersect(halmaz2);

Ebben az esetben az eredmény halmaznak egyetlen eleme van mégpedig a 3-as.

A különbség (Except) műveletnél, azok az elemek fogják az eredményt képezni, amelyek szerepelnek az első halmazban, de a másodikban nem! A különbségképzésnél figyeljünk oda, hogy mikor melyik halmazt vesszük alapul. Ugyanis nem mindegy, hogy melyik halmaz melyiknek a különbsége.

var except = halmaz1.Except(halmaz2);

Ebben az estben az eredmények a következők: 1, 2

var except = halmaz2.Except(halmaz1);

Míg ebben az estben az eredmények: 4, 5

Természetesen nem csak egyszerű tömbökön tudunk ezekkel az operátorokkal dolgozni, hanem komplexebb típusokon is.

Aggregation Operators

Aggregációs kifejezésekkel összesített adatokat tudunk lekérdezni a segítségével. Ezen kifejezésekkel egyszerűsíthetik az elemek megszámolását, összegképezését, átlagát stb.

A Count bővítő metódus egyszerűen végighalad egy szekvencián és visszaadja a szekvencia elemeinek a számát.

var count = halmaz1.Count();

A LongCount hasonló képen működik, mint a Count azzal a különbséggel, hogy visszatérési értéke egy 64 bites integer lesz (long), ezáltal engedélyezve a ~2 milliárdnál nagyobb elemszámokat.

A SUM metódus az adott elemek összegét számolja ki.

var sum = halmaz1.Sum();

Eredmény: 6

Persze mint a többi kifejezésnél ezek a metódusok se csak az egyszerű elemekre használhatók. Nézzük meg például, hogy a Person listánk 4 felhasználójának mennyi az életkoruk összesen. Ebben az esetben a selectorral határozzuk meg, hogy melyik elemet szeretnénk summázni.

var sumResult = persons.Sum(s => s.Age);

Eredmény: 105

Mint látható ebben a kifejezésben speciálisan kiválasztottuk azt az elemet, amit summázni szeretnénk, hisz ha nem tettük volna meg akkor a Person Lista objektumait próbálná meg.

Az Average bővítő metódussal az elemek átlagát számolhatjuk ki. Itt is mint a többi aggregáló kifejezésnél használhatjuk a selector-t

var avg = halmaz1.Average();

Eredmény: 2

var avgResult = persons.Average(s => s.Age);

Eredmény: 26,25

Ha túl nagy a számok összege, akkor OverflowExcelptiont dobhat!

A Minimummal az adott gyűjtemény legkisebb elemét kérdezhetjük le.

var min = halmaz1.Min();

Eredmény: 1

var minResult = persons.Min(s => s.Age);

Eredmény: 25

Maximummal értelemszerűen a gyűjtemény legnagyobb elemét kérdezzük le.

var max = halmaz1.Max()

Eredmény: 5

var maxResult = persons.Max(s => s.Age);

Eredmény: 28image

Ha a gyűjtemény nem valósítja meg az IComperable<Tsource> interface-t akkor a műveletek eredménye egy ArgumentException lesz. (Az alábbi hibaüzenetet kapjuk: At least one object must implement IComparable.”

Például: Az alábbi kifejezés a fentebb említett hibát dobhatja:

var exp = (from c in persons

           select c).Min();

Generation Operators

A Range segítségével egy olyan enumerációt készíthetünk amely, egy start elemtől megy, egy maghatározott count elemig.image

Például: Az alábbi kód, egy olyan gyűjteményt készít ami 2000-től tartalmazó számokat tartalmazza 2009-el bezárólag.

var res = Enumerable.Range(2000, 10);

Az Empty segítségével egy megadott elemből készít enumerációt. Akkor lehet hasznos, ha inicializálni szeretnénk egy gyűjteményt.

var person = Enumerable.Empty<Person>();

Advertisements
Kategóriák:.NET, C#, Linq Címke: , , , ,
  1. joesimon
    2011. június 10. péntek - 18:03

    Jó ez a cikk sorozat.
    Az Enumerable.Empty mire való pontosan? Nem teljesen értettem.
    Ha inicializálni akarunk egy gyűjteményt akkor miért nem jó “new”-al?

    • reiteristvan
      2011. június 11. szombat - 19:32

      A new minden alkalommal új objektumot hoz létre, míg az Empty ezt csak egyszer teszi meg és onnantól singletonként működik (itt ugye felhasználjuk, hogy minden generikus típusparaméterhez külön példányok tartoznak, illetve maga az Emtpy egy EmptyEnumerable nevű osztály statikus metódusát hívja, amely visszaadja az aktuális típusnak megfelelő objektumot),

      Összegezve: ha sokszor kell inicializálni egy gyűjteményt akkor az Emtpy a jobb választás, mert nem terheli a garbage collectort felesleges objektumokkal.

  2. Bencze Zoltán
    2011. szeptember 17. szombat - 20:57

    Egy apró hibára hívnám fel a figyelmet: a halmaz1.Max() = 3 és nem 5.
    Korábban is előfordultak apróságok, ahol pl a 3. Linq részben a 14-es példa
    “var res = persons.OrderByDescending(c => c.Name).Select(c => c);” helyett csak OrderBy(…)

    Lenne egy kérdésem. Észrevettem, hogy ha new az SQL szerű szintaktikát használom, akkor sok esetben elhagyható a Select. Pl.:
    var res = people.OrderBy(p => p.Name);
    foreach (var item in res)
    {
    Console.WriteLine(item);
    }
    Nem csak lefordul, hanem ki is írja a megfelelő megoldást (a példában még van egy .Select(p => p) a végén). (Ja igen, én a Person osztályban felülírtam a ToString() metódust, de gondolom ennek semmi köze nincs hozzá.

    Összességében nagyon jó a sorozat, sokat tanultam belőle.

    Üdvözlettel, Bencze Zoli

  3. Buzatti
    2012. október 3. szerda - 08:57

    Nekem is nagyon tetszik és hálás vagyok a blogodért, remélem lesz folytatás!

  1. No trackbacks yet.

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s

%d blogger ezt kedveli: