Tömbök

A programnyelvek egyik legalapvetőbb adattípusa a tömb , ami ugye egy olyan változó, amely értékek egy halmazát tartalmazza. Nézzük meg az egyszerű tömböktől kezdve a többdimenziós tömbökig a lehetőségeket!

Egyszerű tömbök

A PowerShell nagyon rugalmasan, akár a parancssorban gyorsan begépelhető módon kezeli a tömböket:

[17] PS C:\> $egésztömb = 1,2,11,22,100

[18] PS C:\> $egésztömb

1

2

11

22

100

[19] PS C:\> $egésztömb.gettype()

 

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     Object[]                                 System.Array

Látszik, hogy a tömbök létrehozásához és adatainak megadásához legegyszerűbben a vessző (, ) karakter használatos.

A PowerShellben a tömbök nem csak egyforma típusú elemeket tartalmazhatnak:

[21] PS C:\> $vegyestömb = "szöveg", 123, 666d, 3.1415

[22] PS C:\> $vegyestömb

szöveg

123

666

3,1415

Hogyan lehet egyelemű  tömböt létrehozni?

[23] PS C:\> $nemegyelemű = "elem"

[24] PS C:\> $nemegyelemű

elem

[25] PS C:\> $nemegyelemű.GetType()

 

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     String                                   System.Object

A fenti példában a [23]-as promptnál látszik, hogy egyszerűen egy tagot megadva természetesen – ahogy korábban is láttuk – nem jön létre egyelemű tömb. De egy kis trükkel ez is megoldható:

[26] PS C:\> $egyelemű = ,"elem"

[27] PS C:\> $egyelemű

elem

[28] PS C:\> $egyelemű.gettype()

 

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     Object[]                                 System.Array

Ilyenkor tehát a [26]-os promptban alkalmazott trükköt érdemes használni, azaz az elem elé egy vesszőt kell rakni.

Mi van akkor, ha üres tömböt akarunk létrehozni, mert majd később, egy ciklussal akarjuk feltölteni elemekkel? Ehhez ezt a formátumot lehet használni:

[29] PS C:\> $ürestömb = @()

[30] PS C:\> $ürestömb.GetType()

 

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     Object[]                                 System.Array

Ezt a „@()” jelölést természetesen egy- és többelemű tömbök létrehozására is felhasználhatjuk:

[31] PS C:\> $eet = @(1)

[32] PS C:\> $eet

1

[33] PS C:\> $eet.GetType()

 

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     Object[]                                 System.Array

 

 

[34] PS C:\> $tet = @(1,2,3,4)

[35] PS C:\> $tet

1

2

3

4

[36] PS C:\> $tet.GetType()

 

IsPublic IsSerial Name                                     BaseType

-------- -------- ----                                     --------

True     True     Object[]                                 System.Array

Ha már ennyit foglalkoztunk tömbökkel, nézzük meg, hogy milyen tulajdonságaik és metódusaik vannak:

[37] PS C:\> $tet | Get-Member

 

 

   TypeName: System.Int32

 

Name        MemberType Definition

----        ---------- ----------

CompareTo   Method     System.Int32 CompareTo(Object value), System.Int3...

Equals      Method     System.Boolean Equals(Object obj), System.Boolean...

GetHashCode Method     System.Int32 GetHashCode()

GetType     Method     System.Type GetType()

GetTypeCode Method     System.TypeCode GetTypeCode()

ToString    Method     System.String ToString(), System.String ToString(...

Hoppá! Ez valahogy nem jó! A négy számot tartalmazó tömbünk esetében a Get-Member nem magának a tömbnek, hanem a tömb egyes elemeinek adta meg a tagjellemzőit. Hogyan lehetne rábírni, hogy magának a tömbnek a tagjellemzőit adja vissza? Segíteni kell az előbb látott, egyelemű tömbre vonatkozó (,) trükkel:

[38] PS C:\> ,$tet | Get-Member

 

 

   TypeName: System.Object[]

 

Name               MemberType    Definition

----               ----------    ----------

Count              AliasProperty Count = Length

Address            Method        System.Object& Address(Int32 )

Clone              Method        System.Object Clone()

CopyTo             Method        System.Void CopyTo(Array array, Int32 i...

Equals             Method        System.Boolean Equals(Object obj)

Get                Method        System.Object Get(Int32 )

GetEnumerator      Method        System.Collections.IEnumerator GetEnume...

GetHashCode        Method        System.Int32 GetHashCode()

GetLength          Method        System.Int32 GetLength(Int32 dimension)

GetLongLength      Method        System.Int64 GetLongLength(Int32 dimens...

GetLowerBound      Method        System.Int32 GetLowerBound(Int32 dimens...

GetType            Method        System.Type GetType()

GetUpperBound      Method        System.Int32 GetUpperBound(Int32 dimens...

GetValue           Method        System.Object GetValue(Params Int32[] i...

get_IsFixedSize    Method        System.Boolean get_IsFixedSize()

get_IsReadOnly     Method        System.Boolean get_IsReadOnly()

get_IsSynchronized Method        System.Boolean get_IsSynchronized()

get_Length         Method        System.Int32 get_Length()

get_LongLength     Method        System.Int64 get_LongLength()

get_Rank           Method        System.Int32 get_Rank()

get_SyncRoot       Method        System.Object get_SyncRoot()

Initialize         Method        System.Void Initialize()

Set                Method        System.Void Set(Int32 , Object )

SetValue           Method        System.Void SetValue(Object value, Int3...

ToString           Method        System.String ToString()

IsFixedSize        Property      System.Boolean IsFixedSize {get;}

IsReadOnly         Property      System.Boolean IsReadOnly {get;}

IsSynchronized     Property      System.Boolean IsSynchronized {get;}

Length             Property      System.Int32 Length {get;}

LongLength         Property      System.Int64 LongLength {get;}

Rank               Property      System.Int32 Rank {get;}

SyncRoot           Property      System.Object SyncRoot {get;}

Vajon miért nem ez az alapértelmezett működése a Get-Member -nek? A PowerShell alkotói próbáltak mindig olyan megoldásokat kitalálni, ami a gyakoribb felhasználási esetekre ad jó megoldást, márpedig inkább az a gyakoribb, hogy egy tömb elemeinek keressük a tagjellemzőit, nem pedig magának a tömbnek.

Van egy másik módszer is, amivel az „egész” objektum tagjellemzőit tudjuk megnézni:

[40] PS C:\> Get-Member -InputObject $tet

 

 

   TypeName: System.Object[]

 

Name           MemberType    Definition

----           ----------    ----------

Count          AliasProperty Count = Length

Address        Method        System.Object&, mscorlib, Version=2.0.0.0, Cul...

Clone          Method        System.Object Clone()

A fenti tagjellemzőkből nézzük meg a fontosabbakat:

[46] PS C:\> $tet.count # elemszám

4

[47] PS C:\> $tet.length # elemszám

4

[48] PS C:\> $tet.rank # dimenzió

1

[49] PS C:\> $tet.isfixedsize # fix méretű?

True

(A ’#’ jel megjegyzést jelöl, az ez utáni részt a parancsértelmező nem veszi figyelembe.) A fenti listában látjuk, hogy kétféle szintaxissal is lekérhetjük a tömb elemszámát, lekérhetjük, hogy hány dimenziós a tömb és hogy bővíthetjük-e a tömbünk elemszámát. Ez utóbbi szomorú eredményt ad, hiszen azt mondja, hogy ez fixméretű tömb, nem lehet elemeket hozzáadni. Vajon tényleg?

[54] PS C:\> $tet

1

2

3

4

[55] PS C:\> $tet += 11

[56] PS C:\> $tet

1

2

3

4

11

Azt láthatjuk, hogy az eredetileg négyelemű tömböt minden nehézség nélkül tudtuk öteleműre bővíteni a +=  operátorral. Ez azonban valójában nem ilyen egyszerűen ment végbe a felszín alatt, hanem a PowerShell létrehozott egy új, üres tömböt és szépen átmásolta az eredeti tömbünk elemeit, majd hozzábiggyesztette az új tagot. Természetesen ezt az új tömböt továbbra is a régi név alatt érjük el, de ez már valójában nem ugyanaz a tömb. Ez akkor érdekes, ha nagyon nagyméretű tömbökkel dolgozunk, hiszen akkor az új tömb felépítése során a művelet végrehajtásának végéig ideiglenesen kétszer is tárolódik a tömb, ami jelentős memória-felhasználást igényelhet.

Megjegyzés

Vigyázzunk a tömbök másolásakor! Merthogy a másolás valójában referencia alapján, azaz a memóriacím alapján történik a háttérben, azaz igazából ugyanaz a tömbünk van kétszer:

[1] PS C:\> $tömb1 = "a", "b", "c", "d"

[2] PS C:\> $tömb2 = $tömb1

[3] PS C:\> $tömb2

a

b

c

d

[4] PS C:\> $tömb1[0] = 1

[5] PS C:\> $tömb2

1

b

c

d

Azaz készítek egy tömböt [1], majd azt „átmásolom” egy másik változóba [2-3], majd módosítom az első tömb első elemét [4]. És mi történt? A második tömb első eleme is változott! [5]

Itt most kapóra jön nekünk viszont ennek a tömbtípusnak a „hiányossága”, azaz hogy nem lehet bővíteni, hanem az elem hozzáadása valójában új tömböt hoz létre:

[6] PS C:\> $tömb1 += "e"

[7] PS C:\> $tömb2

1

b

c

d

[8] PS C:\> $tömb1[0] = 2

[9] PS C:\> $tömb2

1

b

c

d

Látható, hogy mihelyst új elemet raktam az első tömbbe, az függetlenedett a másodiktól.

Most már csak egy dolgot nem mutattam meg, hogy hogyan lehet hivatkozni a tömbelem ekre:

[91] PS C:\> $scal[0] # első elem

1

[92] PS C:\> $scal[2..5] # harmadiktól hatodik elemig

3

4

5

200

[93] PS C:\> $scal[5..2] # hatodiktól harmadik elemig

200

5

4

3

A fenti példákban látható, hogy a tömbök első elemére a 0-s indexszel lehet hivatkozni. Egyszerre több egymás utáni elemre a (.. ) range , azaz tartomány operátorral. Ugyan operátorokkal később foglalkozom, de ez a „range” operátor annyira kötődik a tömbökhöz, hogy érdemes itt tárgyalni. Az alábbi példa mutatja az alapvető működését:

[94] PS C:\> 1..10

1

2

3

4

5

6

7

8

9

10

A range segítségével egy másik, érdekes módon is lehet hivatkozni a tömbelemekre, de az csak a „hagyományos” array-re működik:

[95] PS C:\> $a=1,2,3,4,10,8

[96] PS C:\> $a

1

2

3

4

10

8

[97] PS C:\> $a[-1..-3]

8

10

4

A [97]-es prompt azt mutatja, hogy értelmezett a negatív index, amit a PowerShell a tömb utolsó elemétől visszafele számol. A -1. elem az utolsó elem, -2. az utolsó előtti és így tovább.

Ha több elem kellene egyszerre? Adjunk meg bátran több indexet egyszerre! Ebben az esetben természetesen a visszakapott érték is egy tömb lesz.

PS C:\> $b = 1..100

PS C:\> $b[5,7,56]

6

8

57

Az már csak hab a tortán, hogy nemcsak konkrét indexet, hanem intervallumot (sőt akár több intervallumot) adhatunk meg ebben az esetben is.

PS C:\> $b = 1..100

PS C:\> $b[2..4 + 56..58]

3

4

5

57

58

59

Megjegyzés

PowerShell 3.0-tól kezdve már az alapértelmezett tömb is kicsit „okosabb”, mint a korábban látható 2.0-ás tömb:

PS C:\> Get-Member -InputObject (1,2)

 

 

   TypeName: System.Object[]

 

Name           MemberType            Definition

----           ----------            ----------

Count          AliasProperty         Count = Length

Add            Method                int IList.Add(System.Object value)

Address        Method                System.Object&, mscorlib, Version=4.0....

Clear          Method                void IList.Clear()

Clone          Method                System.Object Clone(), System.Object I...

CompareTo      Method                int IStructuralComparable.CompareTo(Sy...

Contains       Method                bool IList.Contains(System.Object value)

CopyTo         Method                void CopyTo(array array, int index), v...

Equals         Method                bool Equals(System.Object obj), bool I...

Get            Method                System.Object Get(int )

GetEnumerator  Method                System.Collections.IEnumerator GetEnum...

GetHashCode    Method                int GetHashCode(), int IStructuralEqua...

GetLength      Method                int GetLength(int dimension)

GetLongLength  Method                long GetLongLength(int dimension)

GetLowerBound  Method                int GetLowerBound(int dimension)

GetType        Method                type GetType()

GetUpperBound  Method                int GetUpperBound(int dimension)

GetValue       Method                System.Object GetValue(Params int[] in...

IndexOf        Method                int IList.IndexOf(System.Object value)

Initialize     Method                void Initialize()

Insert         Method                void IList.Insert(int index, System.Ob...

Remove         Method                void IList.Remove(System.Object value)

RemoveAt       Method                void IList.RemoveAt(int index)

Set            Method                void Set(int , System.Object )

SetValue       Method                void SetValue(System.Object value, int...

ToString       Method                string ToString()

Item           ParameterizedProperty System.Object IList.Item(int index) {g...

IsFixedSize    Property              bool IsFixedSize {get;}

IsReadOnly     Property              bool IsReadOnly {get;}

IsSynchronized Property              bool IsSynchronized {get;}

Length         Property              int Length {get;}

LongLength     Property              long LongLength {get;}

Rank           Property              int Rank {get;}

SyncRoot       Property              System.Object SyncRoot {get;}

Látható, hogy kibővült a metódusok listája az Add és a Remove-al, ami hatékonyabbá teszi a tömbök bővítését a += operátor használatához képest.

Nagyobb tudású tömbök speciális célokra

A .NET Frameworkben van az előzőekben látott [system.object[]]-nél többfajta „okosabb” tömb is, melyeket különböző célokra használhatjuk PowerShellben. Az egyik ilyen a System.Collections.ArrayList  típus, mely leginkább hasonlít az egyszerű tömbre. Nézzük meg ennek a tagjellemzőit:

PS C:\> $scal = New-Object system.collections.arraylist

PS C:\> gm -InputObject $scal

 

 

   TypeName: System.Collections.ArrayList

 

Name           MemberType            Definition

----           ----------            ----------

Add            Method                int Add(System.Object value), int IL...

AddRange       Method                void AddRange(System.Collections.ICo...

BinarySearch   Method                int BinarySearch(int index, int coun...

Clear          Method                void Clear(), void IList.Clear()

Clone          Method                System.Object Clone(), System.Object...

Contains       Method                bool Contains(System.Object item), b...

CopyTo         Method                void CopyTo(array array), void CopyT...

Equals         Method                bool Equals(System.Object obj)

GetEnumerator  Method                System.Collections.IEnumerator GetEn...

GetHashCode    Method                int GetHashCode()

GetRange       Method                System.Collections.ArrayList GetRang...

GetType        Method                type GetType()

IndexOf        Method                int IndexOf(System.Object value), in...

Insert         Method                void Insert(int index, System.Object...

InsertRange    Method                void InsertRange(int index, System.C...

LastIndexOf    Method                int LastIndexOf(System.Object value)...

Remove         Method                void Remove(System.Object obj), void...

RemoveAt       Method                void RemoveAt(int index), void IList...

RemoveRange    Method                void RemoveRange(int index, int count)

Reverse        Method                void Reverse(), void Reverse(int ind...

SetRange       Method                void SetRange(int index, System.Coll...

Sort           Method                void Sort(), void Sort(System.Collec...

ToArray        Method                System.Object[] ToArray(), array ToA...

ToString       Method                string ToString()

TrimToSize     Method                void TrimToSize()

Item           ParameterizedProperty System.Object Item(int index) {get;s...

Capacity       Property              int Capacity {get;set;}

Count          Property              int Count {get;}

IsFixedSize    Property              bool IsFixedSize {get;}

IsReadOnly     Property              bool IsReadOnly {get;}

IsSynchronized Property              bool IsSynchronized {get;}

SyncRoot       Property              System.Object SyncRoot {get;}

Itt már egész fejlett lehetőségeket találunk. Van itt Add metódus, amivel lehet egy elemet hozzáadni, az AddRange-el meg sok elemet, meg van Contains, amivel lehet megvizsgálni, hogy egy adott érték benne van-e a tömbben, az Insert metódussal be lehet szúrni elemeket, a Remove-val el lehet távolítani egy elemet annak értéke alapján, vagy a RemoveAt-tel pozíció alapján, a Reverse-zel meg lehet fordítani az elemek sorrendjét, a Sort-tal sorba lehet rendezni:

[67] PS C:\> $scal = [system.collections.arraylist] (1,2,3,4,5)

[68] PS C:\> $scal

1

2

3

4

5

[69] PS C:\> $scal.Contains(4)

True

[70] PS C:\> $scal.add(1000)

5

[71] PS C:\> $scal

1

2

3

4

5

1000

[72] PS C:\> $scal.insert(3, 200)

[73] PS C:\> $scal

1

2

3

200

4

5

1000

[74] PS C:\> $scal.reverse()

[75] PS C:\> $scal

1000

5

4

200

3

2

1

[76] PS C:\> $scal.sort()

[77] PS C:\> $scal

1

2

3

4

5

200

1000

Az Add-nél vigyázni kell, hogy kimenetet ad, méghozzá azt a számot, ahanyadik elemként tette hozzá az éppen hozzáadott elemet. Ha ez nem kell, akkor el lehet „fojtani” a kimenetet az alábbi két módszer valamelyikével:

[78] PS C:\> [void] $scal.add(1234)

 

[79] PS C:\> $scal.add(2345) > $null

A [78]-es promptban átkonvertáljuk a kimenetet [void]  típussá, azaz semmivé. A [79]-as sorban pedig átirányítjuk a semmibe a kimenetet.

Megjegyzés

Nem mindegy, hogy hogyan adunk elemet egy ilyen „okos” tömbhöz. Az előző megjegyzésben láthattuk, hogy a tömbök másolása változók között valójában csak a tömb címét másolja, mindkét változó ugyanarra a tömbre mutat. Ugyanez igaz a collections.arraylist tömbre is. Ez az ugyanoda mutatás megszűnik, ha a += operátorral bővítem a tömböt, viszont nem szűnik meg, ha az Add() metódust használjuk:

PS C:\> $ot1 = [collections.arraylist] (1,2,3,4,5)

PS C:\> $ot2 = $ot1

PS C:\> $ot1[0]="a"

PS C:\> $ot2

a

2

3

4

5

PS C:\> $ot1 += 6

PS C:\> $ot2

a

2

3

4

5

PS C:\> $ot1.GetType().FullName

System.Object[]

A fenti példában látható, hogy míg az „a” érték beadása a 0. elemként mind az $ot1, mind at $ot2-re érvényes volt, addig a $ot1 +=-vel történő bővítése után az már egy másik tömb lett $ot2-höz képest, a típusa is átváltozott System.Object[]-re.

Ezzel szemben, ha az Add metódust használjuk, minden marad az eredeti típusban és a két változó közti referencia is megmarad:

PS C:\> $ot1 = [collections.arraylist] (1,2,3,4,5)

PS C:\> $ot2 = $ot1

PS C:\> $ot1.add(6)

5

PS C:\> $ot2

1

2

3

4

5

6

PS C:\> $ot1.GetType().FullName

System.Collections.ArrayList

Az arraylist-nek van még bináris keresője is! Ha sorrendben tartjuk benne az elemeket, akkor a binarysearch nagyon gyorsan megadja azt az indexet, ahol az elem található. Ha nincs benne, akkor azt a negatív számot adja meg, aminek ellentettjéből kivonva egyet lenne az az index, ahol az elemnek lennie kéne:

PS C:\> $bs = [collections.arraylist] (1..20 + 22..40)

PS C:\> $bs.BinarySearch(20)

19

PS C:\> $bs.BinarySearch(21)

-21

A fenti példában csináltam egy számsort 1-től 40-ig, amiből hiányzik a 21-es érték. A BinarySearch a 20-ra megadja a 19-es index értéket, a 21-re viszont -21-et ad, aminek ellentettjének egyel kevesebb értéke 20, itt lenne a 21, illetve ide lehet berakni, ha az lenne a feladat:

PS C:\> $bs.Insert(20,21)

Az ArrayList elemei indexelhetők:

PS C:\> $bs[5]

6

Ezt azért fontos hangsúlyozni, mert a következő két tömbtípusnál csak egy bizonyos elemet lehet megnézni vagy kivenni, viszont bizonyos célokra pont erre lehet szükségünk.

A következő speciális tömbváltozat a [systems.collections.queue]  sor:

PS C:\> $queue = [System.Collections.Queue] @()

PS C:\> Get-Member -InputObject $queue

 

 

   TypeName: System.Collections.Queue

 

Name           MemberType Definition

----           ---------- ----------

Clear          Method     void Clear()

Clone          Method     System.Object Clone(), System.Object ICloneable...

Contains       Method     bool Contains(System.Object obj)

CopyTo         Method     void CopyTo(array array, int index), void IColl...

Dequeue        Method     System.Object Dequeue()

Enqueue        Method     void Enqueue(System.Object obj)

Equals         Method     bool Equals(System.Object obj)

GetEnumerator  Method     System.Collections.IEnumerator GetEnumerator(),...

GetHashCode    Method     int GetHashCode()

GetType        Method     type GetType()

Peek           Method     System.Object Peek()

ToArray        Method     System.Object[] ToArray()

ToString       Method     string ToString()

TrimToSize     Method     void TrimToSize()

Count          Property   int Count {get;}

IsSynchronized Property   bool IsSynchronized {get;}

SyncRoot       Property   System.Object SyncRoot {get;}

A metódusaiból látható, hogy az Enqueue-val lehet elemeket berakni, Peek-el lehet belekukcskálni, hogy melyik az az elem, ami kivétel szempontjából a következő lesz a sorban, Dequeue-val lehet kivenni a legkorábban berakott elemet:

PS C:\> $queue.Enqueue(1)

PS C:\> $queue.Enqueue("a")

PS C:\> $queue.Enqueue(2)

PS C:\> $queue.Enqueue("b")

PS C:\> $queue.Peek()

1

PS C:\> $queue

1

a

2

b

PS C:\> $queue.Dequeue()

1

PS C:\> $queue

a

2

b

Azaz ez egy FIFO (first in, first out) sor. Ha olyan feladatunk van, amiben a sorrendtartó elemkezelés fontos, akkor ez a típus jó szolgálatot tehet.

Egy másik tömbváltozat a [system.collections.stack]  zsák. Ennek az a jellegzetessége, hogy pont fordított módon működik a sorhoz képeset, azaz FILO (first in, last out) módon:

PS C:\> $stack = [System.Collections.Stack] @()

PS C:\> Get-Member -InputObject $stack

 

 

   TypeName: System.Collections.Stack

 

Name           MemberType Definition

----           ---------- ----------

Clear          Method     void Clear()

Clone          Method     System.Object Clone(), System.Object ICloneable...

Contains       Method     bool Contains(System.Object obj)

CopyTo         Method     void CopyTo(array array, int index), void IColl...

Equals         Method     bool Equals(System.Object obj)

GetEnumerator  Method     System.Collections.IEnumerator GetEnumerator(),...

GetHashCode    Method     int GetHashCode()

GetType        Method     type GetType()

Peek           Method     System.Object Peek()

Pop            Method     System.Object Pop()

Push           Method     void Push(System.Object obj)

ToArray        Method     System.Object[] ToArray()

ToString       Method     string ToString()

Count          Property   int Count {get;}

IsSynchronized Property   bool IsSynchronized {get;}

SyncRoot       Property   System.Object SyncRoot {get;}

A metódusai hasonlóak a soréhoz, csak itt Push-sal teszünk be elemet, Pop-pal vesszük ki, de ugyanúgy Peek-kel nézünk bele:

PS C:\> $stack.Push(1)

PS C:\> $stack.Push("a")

PS C:\> $stack.Push(2)

PS C:\> $stack.Push("b")

PS C:\> $stack.Peek()

b

PS C:\> $stack

b

2

a

1

PS C:\> $stack.Pop()

b

PS C:\> $stack

2

a

1

Ezt olyan esetekben célszerű használni, ahol épp mindig a legutóbb berakott elemekre van szükségünk.

Többdimenziós tömbök

Természetesen egy tömbnek nem csak egyirányú kiterjedése lehet, tudunk többdimenziós  tömböket is létrehozni. Az alábbi példában úgy érem el a kétirányú kiterjedést, hogy a $tábla tömb elemeiként szintén tömböket teszek:

[1] PS C:\> $tábla = (1,2,3,4),("a","b","c","d")

[2] PS C:\> $tábla

1

2

3

4

a

b

c

d

[3] PS C:\> $tábla[0][0]

1

[4] PS C:\> $tábla[0][1]

2

[5] PS C:\> $tábla[1][0]

a

Látszik, hogy ilyenkor két indexszel hivatkozhatunk a „dimenziókra”. Sőt! Nem csak egyforma „hosszú” sorokból állhat egy „kvázi” kétdimenziós tömb:

[7] PS C:\> $vegyes = (1,2,3),("a","b"),("egy","kettő","három","négy")

[8] PS C:\> $vegyes[0][0]

1

[9] PS C:\> $vegyes[0][2]

3

[10] PS C:\> $vegyes[0][3]

[11] PS C:\> $vegyes[1][1]

b

[12] PS C:\> $vegyes[1][2]

[13] PS C:\> $vegyes[2][3]

négy

Az „igazi” többdimenziós tömböt az alábbi szintaxissal lehet hivatalosan létrehozni, és ilyenkor másként kell hivatkozni a tömbelemekre:

[20] PS C:\> $igazi = new-object -TypeName 'object[,]' -ArgumentList 3,2

[21] PS C:\> $igazi[2,1]="kakukk"

Természetesen nem csak kettő, hanem akárhány dimenziós lehet egy tömb, de ilyet valószínű csak a robottechnikában használnak. Példa egy tízdimenziós tömbre:

[23] PS C:\> $igazi = new-object 'object[,,,,,,,,,]' 8,3,7,5,6,7,8,9,10,3

Típusos tömbök

Tudunk létrehozni típusos tömböket , amelyek csak az adott típusú elemeket tartalmazhatnak:

[24] PS C:\> $t = New-Object int[] 20

[25] PS C:\> $t[1]="szöveg"

Array assignment to [1] failed: Cannot convert value "szöveg" to type "Sy

stem.Int32". Error: "Input string was not in a correct format.".

At line:1 char:4

+ $t[ <<<< 1]="szöveg"

    + CategoryInfo          : InvalidOperation: (szöveg:String) [], Runt

   imeException

    + FullyQualifiedErrorId : ArrayAssignmentFailed

[26] PS C:\> $t += 2

A fenti példában látszik, hogy létrehozunk előre egy 20 elemű int típusú tömböt, amibe ha szöveget akarunk betölteni, akkor hibát kapunk. Azonban ha új elemet biggyesztünk hozzá, akkor az már lehet akármilyen típusú.

Természetesen típusos tömbökből többdimenziósakat is létre tudunk hozni:

[27] PS C:\> $ttdt = New-Object 'int[,]' 5,2

[28] PS C:\> $ttdt[0,0] = 12

[29] PS C:\> $ttdt[1,1] = "próba"

Array assignment to [1,1] failed: Cannot convert value "próba" to type "System

.Int32". Error: "Input string was not in a correct format.".

At line:1 char:7

+ $ttdt[ <<<< 1,1] = "próba"

    + CategoryInfo          : InvalidOperation: (próba:String) [], RuntimeExc

   eption

    + FullyQualifiedErrorId : ArrayAssignmentFailed

Itt tehát annyi a különbség, hogy nem általános object-ek a tömb elemei, hanem itt a példában int típus. A [29]-es sorban nem is szerette, ha sztringet akartam beletenni.

Generic adattípus – paraméterezhető típusos tömb

A .NET keretrendszer tartalmaz egy olyan tömböt, aminek paraméterként adható át, hogy milyen elemeket tartalmazhasson:

PS C:\> $type = "string"

PS C:\> $genlist = New-Object "collections.generic.list[$type]"

PS C:\> get-member -InputObject $genlist

 

 

   TypeName: System.Collections.Generic.List`1[[System.String, mscorlib, Versi

on=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

 

Name           MemberType            Definition

----           ----------            ----------

Add            Method                void Add(string item), void ICollectio...

AddRange       Method                void AddRange(System.Collections.Gener...

AsReadOnly     Method                System.Collections.ObjectModel.ReadOnl...

BinarySearch   Method                int BinarySearch(int index, int count,...

Clear          Method                void Clear(), void ICollection[string]...

Contains       Method                bool Contains(string item), bool IColl...

ConvertAll     Method                System.Collections.Generic.List[TOutpu...

CopyTo         Method                void CopyTo(string[] array), void Copy...

Equals         Method                bool Equals(System.Object obj)

Exists         Method                bool Exists(System.Predicate[string] m...

Find           Method                string Find(System.Predicate[string] m...

FindAll        Method                System.Collections.Generic.List[string...

FindIndex      Method                int FindIndex(System.Predicate[string]...

FindLast       Method                string FindLast(System.Predicate[strin...

FindLastIndex  Method                int FindLastIndex(System.Predicate[str...

ForEach        Method                void ForEach(System.Action[string] act...

GetEnumerator  Method                System.Collections.Generic.List`1+Enum...

GetHashCode    Method                int GetHashCode()

GetRange       Method                System.Collections.Generic.List[string...

GetType        Method                type GetType()

IndexOf        Method                int IndexOf(string item), int IndexOf(...

Insert         Method                void Insert(int index, string item), v...

InsertRange    Method                void InsertRange(int index, System.Col...

LastIndexOf    Method                int LastIndexOf(string item), int Last...

Remove         Method                bool Remove(string item), bool ICollec...

RemoveAll      Method                int RemoveAll(System.Predicate[string]...

RemoveAt       Method                void RemoveAt(int index), void IList[s...

RemoveRange    Method                void RemoveRange(int index, int count)

Reverse        Method                void Reverse(), void Reverse(int index...

Sort           Method                void Sort(), void Sort(System.Collecti...

ToArray        Method                string[] ToArray()

ToString       Method                string ToString()

TrimExcess     Method                void TrimExcess()

TrueForAll     Method                bool TrueForAll(System.Predicate[strin...

Item           ParameterizedProperty string Item(int index) {get;set;}

Capacity       Property              int Capacity {get;set;}

Count          Property              int Count {get;}

IsFixedSize    Property              bool IsFixedSize {get;}

IsReadOnly     Property              bool IsReadOnly {get;}

IsSynchronized Property              bool IsSynchronized {get;}

SyncRoot       Property              System.Object SyncRoot {get;}

Látható, hogy a $genlist objektum létrehozásakor meghatároztam, hogy ez egy olyan típusú tömb legyen, amelynek elemei sztringek lehetnek. Ha kilistázom a tagjellemzőit ennek az objektumnak, akkor láthatjuk, hogy ez is „okos” tömb, azaz itt is van Add() metódus és sok más hasznos dolog.

Halmazok (hashset)

A típusos tömbök egy különleges fajtája a halmaz . A .NET-ben ennek a típusnak teljes neve: System.Collections.Generic.HashSet . Nem tévesztendő össze ez a hashtable adattípussal (ld. a következő fejezetben)!

A halmaz olyan típusos tömb, amiben az elemek egyedieknek kell lenniük.

PS C:\> $set = [System.Collections.Generic.HashSet[string]] ('egy', 'kettő', 'h

árom')

PS C:\> $set

egy

kettő

három

A fenti $set tehát tartalmaz három sztringet. Ha hozzá akarjuk adni újra az ’egy’-et, akkor az Add() metódus eredménye $false-t ad:

PS C:\> $set.Add('egy')

False

Csináljunk egy másik halmazt most a New-Object segítségével és már a kezdeti elemeket is az Add()-el adom meg:

PS C:\> $másik = New-Object System.Collections.Generic.HashSet[string]

PS C:\> $másik.add('egy')

True

PS C:\> $másik.add('négy')

True

A halmazok által nyújtott előnyök a metódusokban találhatók a halmazműveletek képében:

PS C:\> Get-Member -InputObject $másik

 

 

   TypeName: System.Collections.Generic.HashSet`1[[System.String, mscorlib, Ve

rsion=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

 

Name                MemberType Definition

----                ---------- ----------

Add                 Method     bool Add(string item), void ICollection[stri...

Clear               Method     void Clear(), void ICollection[string].Clear()

Contains            Method     bool Contains(string item), bool ICollection...

CopyTo              Method     void CopyTo(string[] array, int arrayIndex),...

Equals              Method     bool Equals(System.Object obj)

ExceptWith          Method     void ExceptWith(System.Collections.Generic.I...

GetEnumerator       Method     System.Collections.Generic.HashSet`1+Enumera...

GetHashCode         Method     int GetHashCode()

GetObjectData       Method     void GetObjectData(System.Runtime.Serializat...

GetType             Method     type GetType()

IntersectWith       Method     void IntersectWith(System.Collections.Generi...

IsProperSubsetOf    Method     bool IsProperSubsetOf(System.Collections.Gen...

IsProperSupersetOf  Method     bool IsProperSupersetOf(System.Collections.G...

IsSubsetOf          Method     bool IsSubsetOf(System.Collections.Generic.I...

IsSupersetOf        Method     bool IsSupersetOf(System.Collections.Generic...

OnDeserialization   Method     void OnDeserialization(System.Object sender)...

Overlaps            Method     bool Overlaps(System.Collections.Generic.IEn...

Remove              Method     bool Remove(string item), bool ICollection[s...

RemoveWhere         Method     int RemoveWhere(System.Predicate[string] match)

SetEquals           Method     bool SetEquals(System.Collections.Generic.IE...

SymmetricExceptWith Method     void SymmetricExceptWith(System.Collections....

ToString            Method     string ToString()

TrimExcess          Method     void TrimExcess()

TryGetValue         Method     bool TryGetValue(string equalValue, [ref] st...

UnionWith           Method     void UnionWith(System.Collections.Generic.IE...

Comparer            Property   System.Collections.Generic.IEqualityComparer...

Count               Property   int Count {get;}

IsReadOnly          Property   bool IsReadOnly {get;}

Nézzük ezeket a halmazműveleteket! Ezek eredményei mindig abba a halmazba kerülnek, amelyen meghívjuk ezeket, azaz az eredeti halmaz felülíródik. Az UnionWith() az unióképzés, azaz a két halmaz egyesítése:

PS C:\> $set.UnionWith($másik); $set

egy

kettő

három

négy

A két egyesített halmaz elemei egyszer szerepelnek az eredményben.

Újra töltöm az eredeti elemekkel a $set-et, nézzük így meg, hogy mit az az IntersectWith(), azaz a metszet:

PS C:\> $set = [System.Collections.Generic.HashSet[string]] ('egy', 'kettő', 'h

árom')

PS C:\> $set.IntersectWith($másik); $set

egy

Itt az eredmény a két halmaz közös elemeiből áll.

Újra töltés után nézzük az ExceptWith()-et, azaz a halmazok különbségét:

PS C:\> $set = [System.Collections.Generic.HashSet[string]] ('egy', 'kettő', 'h

árom')

PS C:\> $set.ExceptWith($másik); $set

kettő

három

Itt az eredeti halmazban azok az elemek maradnak, amik nincsenek benne a metszetben. Ezekkel tulajdonképpen meg is elégedhetnénk, de van még egy: SymmetricExceptWith() adja az unióból kivett metszetet:

PS C:\> $set = [System.Collections.Generic.HashSet[string]] ('egy', 'kettő', 'h

árom')

PS C:\> $set.SymmetricExceptWith($másik); $set

négy

kettő

három

Van még ezeken kívül jónéhány vizsgálatot végző metódus is, amelyekkel azt lehet megnézni, hogy az egyik halmaz tartalmazza-e a másikat.



Word To HTML Converter