Alles wat u wilt weten over matrices
Matrices zijn een fundamentele taalfunctie van de meeste programmeertalen. Ze zijn een verzameling waarden of objecten die moeilijk te vermijden zijn. Laten we eens kijken naar matrices en alles wat ze te bieden hebben.
Notitie
De oorspronkelijke versie van dit artikel verscheen op de blog geschreven door @KevinMarquette. Het PowerShell-team bedankt Kevin voor het delen van deze inhoud met ons. Bekijk zijn blog op PowerShellExplained.com.
Wat is een matrix?
Ik ga beginnen met een eenvoudige technische beschrijving van wat matrices zijn en hoe ze worden gebruikt door de meeste programmeertalen voordat ik overschuif naar de andere manieren waarop PowerShell ze gebruikt.
Een matrix is een gegevensstructuur die fungeert als een verzameling van meerdere items. U kunt de matrix herhalen of afzonderlijke items openen met behulp van een index. De matrix wordt gemaakt als een opeenvolgend segment van het geheugen waarin elke waarde naast de andere waarde wordt opgeslagen.
Ik raak al die details aan terwijl we gaan.
Basisgebruik
Omdat matrices een dergelijke basisfunctie van PowerShell zijn, is er een eenvoudige syntaxis voor het werken met deze matrices in PowerShell.
Een matrix maken
Een lege matrix kan worden gemaakt met behulp van @()
PS> $data = @()
PS> $data.count
0
We kunnen een matrix maken en zaaien met waarden door ze gewoon tussen haakjes @() te plaatsen.
PS> $data = @('Zero','One','Two','Three')
PS> $data.count
4
PS> $data
Zero
One
Two
Three
Deze matrix heeft vier items. Wanneer we de $data variabele aanroepen, zien we de lijst met onze items. Als het een matrix met tekenreeksen is, krijgen we één regel per tekenreeks.
We kunnen een matrix op meerdere regels declareren. De komma is optioneel in dit geval en over het algemeen weggelaten.
$data = @(
'Zero'
'One'
'Two'
'Three'
)
Ik geef de voorkeur aan mijn matrices op meerdere regels als dat. Niet alleen wordt het gemakkelijker om te lezen wanneer u meerdere items hebt, het maakt het ook gemakkelijker om te vergelijken met eerdere versies bij het gebruik van broncodebeheer.
Andere syntaxis
Het wordt vaak begrepen dat @() dit de syntaxis is voor het maken van een matrix, maar door komma's gescheiden lijsten werken meestal.
$data = 'Zero','One','Two','Three'
Write-Output om matrices te maken
Een leuke truc die het vermelden waard is, is dat u snel tekenreeksen kunt Write-Output maken in de console.
$data = Write-Output Zero One Two Three
Dit is handig omdat u geen aanhalingstekens hoeft te plaatsen rond de tekenreeksen wanneer de parameter tekenreeksen accepteert. Ik zou dit nooit doen in een script, maar het is eerlijk spel in de console.
Toegang tot items
Nu u een matrix hebt met items erin, kunt u deze items openen en bijwerken.
Offset
Voor toegang tot afzonderlijke items gebruiken we de vierkante haken [] met een offsetwaarde vanaf 0. Zo krijgen we het eerste item in onze matrix:
PS> $data = 'Zero','One','Two','Three'
PS> $data[0]
Zero
De reden waarom we hier nul gebruiken, is omdat het eerste item zich aan het begin van de lijst bevindt, zodat we een verschuiving van 0 items gebruiken om ernaartoe te komen. Als u naar het tweede item wilt gaan, moet u een verschuiving van 1 gebruiken om het eerste item over te slaan.
PS> $data[1]
One
Dit betekent dat het laatste item op verschuiving 3 staat.
PS> $data[3]
Three
Index
Nu kunt u zien waarom ik de waarden heb gekozen die ik voor dit voorbeeld heb gedaan. Ik heb dit geïntroduceerd als een offset omdat dat echt is, maar deze verschuiving wordt meestal aangeduid als een index. Een index die begint bij 0. Voor de rest van dit artikel noem ik de offset een index.
Speciale index trucs
In de meeste talen kunt u slechts één getal opgeven als index en krijgt u één item terug. PowerShell is veel flexibeler. U kunt meerdere indexen tegelijk gebruiken. Door een lijst met indexen op te geven, kunnen we verschillende items selecteren.
PS> $data[0,2,3]
Zero
Two
Three
De items worden geretourneerd op basis van de volgorde van de opgegeven indexen. Als u een index dupliceren, krijgt u dat item beide keren.
PS> $data[3,0,3]
Three
Zero
Three
We kunnen een reeks getallen opgeven met de ingebouwde .. operator.
PS> $data[1..3]
One
Two
Three
Dit werkt ook omgekeerd.
PS> $data[3..1]
Three
Two
One
U kunt negatieve indexwaarden gebruiken om te compenseren van het einde. Dus als u het laatste item in de lijst nodig hebt, kunt u gebruiken -1.
PS> $data[-1]
Three
Eén woord van voorzichtigheid hier met de .. operator. De reeks 0..-1 en -1..0 evalueert de waarden 0,-1 en -1,0. Het is gemakkelijk te zien $data[0..-1] en te denken dat alle items worden opgesomd als u dit detail vergeet. $data[0..-1] geeft u dezelfde waarde als $data[0,-1] door u het eerste en laatste item in de matrix te geven (en geen van de andere waarden). Hier volgt een groter voorbeeld:
PS> $a = 1,2,3,4,5,6,7,8
PS> $a[2..-1]
3
2
1
8
Dit is hetzelfde als:
PS> $a[2,1,0,-1]
3
2
1
8
Buiten grenzen
Als u in de meeste talen probeert toegang te krijgen tot een index van een item dat voorbij het einde van de matrix ligt, krijgt u een of ander type fout of een uitzondering. PowerShell retourneert niets op de achtergrond.
PS> $null -eq $data[9000]
True
Kan niet indexeren in een null-matrix
Als uw variabele is $null en u probeert deze te indexeren als een matrix, krijgt u een System.Management.Automation.RuntimeException uitzondering met het bericht Cannot index into a null array.
PS> $empty = $null
PS> $empty[0]
Error: Cannot index into a null array.
Zorg er dus voor dat uw matrices zich niet $null bevinden voordat u toegang probeert te krijgen tot elementen erin.
Count
Matrices en andere verzamelingen hebben een tellingseigenschap waarmee wordt aangegeven hoeveel items zich in de matrix bevinden.
PS> $data.count
4
PowerShell 3.0 heeft een tellingseigenschap toegevoegd aan de meeste objecten. u kunt één object hebben en het moet u een telling geven van 1.
PS> $date = Get-Date
PS> $date.count
1
Zelfs $null heeft een tellingseigenschap, behalve dat deze retourneert 0.
PS> $null.count
0
Er zijn hier enkele traps die ik opnieuw ga bekijken wanneer ik de controle op $null of lege matrices verderop in dit artikel bekijk.
Off-by-one-fouten
Er wordt een veelvoorkomende programmeerfout gemaakt omdat matrices beginnen bij index 0. Off-by-one-fouten kunnen op twee manieren worden geïntroduceerd.
De eerste is door geestelijk te denken dat u het tweede item wilt en een index van 2 en echt het derde item wilt gebruiken. Of door te denken dat u vier items hebt en u het laatste item wilt, zodat u het aantal gebruikt om toegang te krijgen tot het laatste item.
$data[ $data.count ]
PowerShell is heel blij dat u dat kunt doen en u precies kunt geven welk item er bestaat in index 4: $null. U moet het gebruik of $data.count - 1 de -1 hierboven besproken informatie gebruiken.
PS> $data[ $data.count - 1 ]
Three
Hier kunt u de -1 index gebruiken om het laatste element op te halen.
PS> $data[ -1 ]
Three
Lee Dailey wees er ook op dat we kunnen gebruiken $data.GetUpperBound(0) om het maximale indexnummer op te halen.
PS> $data.GetUpperBound(0)
3
PS> $data[ $data.GetUpperBound(0) ]
Three
De tweede meest voorkomende manier is wanneer de lijst wordt herhaald en niet op het juiste moment wordt gestopt. Ik ga hier verder mee als we het hebben over het gebruik van de for lus.
Items bijwerken
We kunnen dezelfde index gebruiken om bestaande items in de matrix bij te werken. Dit geeft ons directe toegang om afzonderlijke items bij te werken.
$data[2] = 'dos'
$data[3] = 'tres'
Als we proberen een item bij te werken dat voorbij het laatste element ligt, wordt er een Index was outside the bounds of the array. fout weergegeven.
PS> $data[4] = 'four'
Index was outside the bounds of the array.
At line:1 char:1
+ $data[4] = 'four'
+ ~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException
Ik kom later terug als ik het heb over het maken van een matrix groter.
Iteratie
Op een bepaald moment moet u mogelijk de hele lijst doorlopen of herhalen en een actie uitvoeren voor elk item in de matrix.
Pijplijn
Matrices en de PowerShell-pijplijn zijn voor elkaar bedoeld. Dit is een van de eenvoudigste manieren om deze waarden te verwerken. Wanneer u een matrix doorgeeft aan een pijplijn, wordt elk item in de matrix afzonderlijk verwerkt.
PS> $data = 'Zero','One','Two','Three'
PS> $data | ForEach-Object {"Item: [$PSItem]"}
Item: [Zero]
Item: [One]
Item: [Two]
Item: [Three]
Als je het nog niet eerder hebt gezien $PSItem , weet je gewoon dat het hetzelfde is als $_. U kunt beide gebruiken omdat ze beide het huidige object in de pijplijn vertegenwoordigen.
ForEach-lus
De ForEach lus werkt goed met verzamelingen. Gebruik de syntaxis: foreach ( <variable> in <collection> )
foreach ( $node in $data )
{
"Item: [$node]"
}
ForEach-methode
Ik vergeet deze meestal, maar het werkt goed voor eenvoudige bewerkingen. Met PowerShell kunt u een verzameling aanroepen .ForEach() .
PS> $data.foreach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]
De .foreach() parameter gebruikt een scriptblok. U kunt de haakjes verwijderen en alleen het scriptblok opgeven.
$data.foreach{"Item [$PSItem]"}
Dit is een minder bekende syntaxis, maar werkt precies hetzelfde. Deze foreach methode is toegevoegd in PowerShell 4.0.
For-lus
De for lus wordt in de meeste andere talen intensief gebruikt, maar u ziet deze niet veel in PowerShell. Wanneer u deze ziet, is het vaak in de context van het lopen van een matrix.
for ( $index = 0; $index -lt $data.count; $index++)
{
"Item: [{0}]" -f $data[$index]
}
Het eerste wat we doen, is het initialiseren van een $index .0 Vervolgens voegen we de voorwaarde toe die $index kleiner moet zijn dan $data.count. Ten slotte geven we aan dat telkens wanneer we herhalen dat ik de index moet verhogen door 1. In dit geval $index++ is het kort voor $index = $index + 1. De notatieoperator (-f) wordt gebruikt om de waarde van $data[$index] de uitvoertekenreeks in te voegen.
Wanneer u een for lus gebruikt, moet u speciale aandacht besteden aan de voorwaarde. Ik gebruikte $index -lt $data.count hier. Het is eenvoudig om de voorwaarde iets verkeerd te krijgen om een fout met één fout in uw logica op te halen. Het gebruik $index -le $data.count of $index -lt ($data.count - 1) zijn ooit zo fout. Dit zou ertoe leiden dat uw resultaat te veel of te weinig items verwerkt. Dit is de klassieke off-by-one-fout.
Schakellus
Dit is een die gemakkelijk te overzien is. Als u een matrix opgeeft aan een schakelinstructie, wordt elk item in de matrix gecontroleerd.
$data = 'Zero','One','Two','Three'
switch( $data )
{
'One'
{
'Tock'
}
'Three'
{
'Tock'
}
Default
{
'Tick'
}
}
Tick
Tock
Tick
Tock
Er zijn veel coole dingen die we kunnen doen met de switch-instructie. Ik heb nog een artikel gewijd aan dit.
Waarden bijwerken
Wanneer uw matrix een verzameling tekenreeksen of gehele getallen (waardetypen) is, wilt u soms de waarden in de matrix bijwerken terwijl u ze doorloopt. De meeste bovenstaande lussen gebruiken een variabele in de lus die een kopie van de waarde bevat. Als u die variabele bijwerkt, wordt de oorspronkelijke waarde in de matrix niet bijgewerkt.
De uitzondering op die instructie is de for lus. Als u een matrix wilt doorlopen en waarden erin wilt bijwerken, is de for lus wat u zoekt.
for ( $index = 0; $index -lt $data.count; $index++ )
{
$data[$index] = "Item: [{0}]" -f $data[$index]
}
In dit voorbeeld wordt een waarde per index gebruikt, enkele wijzigingen aangebracht en vervolgens dezelfde index gebruikt om deze weer toe te wijzen.
Matrices van objecten
Tot nu toe is het enige wat we in een matrix hebben geplaatst een waardetype, maar matrices kunnen ook objecten bevatten.
$data = @(
[pscustomobject]@{FirstName='Kevin';LastName='Marquette'}
[pscustomobject]@{FirstName='John'; LastName='Doe'}
)
Veel cmdlets retourneren verzamelingen objecten als matrices wanneer u ze toewijst aan een variabele.
$processList = Get-Process
Alle basisfuncties waarover we al hebben gesproken, zijn nog steeds van toepassing op matrices van objecten met enkele details die u moet vermelden.
Toegang tot eigenschappen
We kunnen een index gebruiken om toegang te krijgen tot een afzonderlijk item in een verzameling, net als bij waardetypen.
PS> $data[0]
FirstName LastName
----- ----
Kevin Marquette
We kunnen eigenschappen rechtstreeks openen en bijwerken.
PS> $data[0].FirstName
Kevin
PS> $data[0].FirstName = 'Jay'
PS> $data[0]
FirstName LastName
----- ----
Jay Marquette
Matrixeigenschappen
Normaal gesproken moet u de hele lijst als deze opsommen om toegang te krijgen tot alle eigenschappen:
PS> $data | ForEach-Object {$_.LastName}
Marquette
Doe
Of met behulp van de Select-Object -ExpandProperty cmdlet.
PS> $data | Select-Object -ExpandProperty LastName
Marquette
Doe
Maar PowerShell biedt ons de mogelijkheid om rechtstreeks aan te vragen LastName . PowerShell bevat ze allemaal voor ons en retourneert een schone lijst.
PS> $data.LastName
Marquette
Doe
De opsomming gebeurt nog steeds, maar we zien de complexiteit er niet achter.
filteren Where-Object
Dit is waar Where-Object we binnenkomen, zodat we kunnen filteren en selecteren wat we uit de matrix willen op basis van de eigenschappen van het object.
PS> $data | Where-Object {$_.FirstName -eq 'Kevin'}
FirstName LastName
----- ----
Kevin Marquette
We kunnen dezelfde query schrijven om de FirstName gezochte query op te halen.
$data | Where FirstName -eq Kevin
Where()
Matrices hebben een Where() methode waarmee u een scriptblock voor het filter kunt opgeven.
$data.Where({$_.FirstName -eq 'Kevin'})
Deze functie is toegevoegd in PowerShell 4.0.
Objecten bijwerken in lussen
Met waardetypen is de enige manier om de matrix bij te werken een for-lus te gebruiken, omdat we de index moeten kennen om de waarde te vervangen. We hebben meer opties met objecten omdat ze verwijzingstypen zijn. Hier volgt een snel voorbeeld:
foreach($person in $data)
{
$person.FirstName = 'Kevin'
}
Deze lus loopt elk object in de $data matrix. Omdat objecten verwijzingstypen zijn, verwijst de $person variabele naar exact hetzelfde object dat zich in de matrix bevindt. Updates van de eigenschappen worden dus wel bijgewerkt met het origineel.
U kunt het hele object nog steeds niet op deze manier vervangen. Als u probeert een nieuw object toe te wijzen aan de $person variabele, werkt u de variabeleverwijzing bij naar iets anders dat niet langer verwijst naar het oorspronkelijke object in de matrix. Dit werkt niet zoals u zou verwachten:
foreach($person in $data)
{
$person = [pscustomobject]@{
FirstName='Kevin'
LastName='Marquette'
}
}
Operators
De operators in PowerShell werken ook aan matrices. Sommigen werken iets anders.
-join
De -join operator is de meest voor de hand liggende operator, dus laten we het eerst bekijken. Ik hou van de -join operator en gebruik het vaak. Hiermee worden alle elementen in de matrix samengevoegd met het teken of de tekenreeks die u opgeeft.
PS> $data = @(1,2,3,4)
PS> $data -join '-'
1-2-3-4
PS> $data -join ','
1,2,3,4
Een van de functies die ik leuk vind aan de -join operator, is dat het enkele items verwerkt.
PS> 1 -join '-'
1
Ik gebruik dit in logboekregistratie en uitgebreide berichten.
PS> $data = @(1,2,3,4)
PS> "Data is $($data -join ',')."
Data is 1,2,3,4.
-join $array
Hier is een slimme truc die Lee Dailey me aanwees. Als u ooit alles wilt samenvoegen zonder scheidingsteken, in plaats van dit te doen:
PS> $data = @(1,2,3,4)
PS> $data -join $null
1234
U kunt de matrix gebruiken -join als parameter zonder voorvoegsel. Bekijk dit voorbeeld om te zien waar ik het over heb.
PS> $data = @(1,2,3,4)
PS> -join $data
1234
-vervangen en -splitsen
De andere operators vinden het leuk -replace om elk item in de matrix uit te voeren en -split uit te voeren. Ik kan niet zeggen dat ik ze ooit op deze manier heb gebruikt, maar hier is een voorbeeld.
PS> $data = @('ATX-SQL-01','ATX-SQL-02','ATX-SQL-03')
PS> $data -replace 'ATX','LAX'
LAX-SQL-01
LAX-SQL-02
LAX-SQL-03
-contains
Met de -contains operator kunt u een matrix met waarden controleren om te zien of deze een opgegeven waarde bevat.
PS> $data = @('red','green','blue')
PS> $data -contains 'green'
True
-in
Wanneer u één waarde hebt die u wilt controleren, komt overeen met een van de verschillende waarden, kunt u de -in operator gebruiken. De waarde bevindt zich aan de linkerkant en de matrix aan de rechterkant van de operator.
PS> $data = @('red','green','blue')
PS> 'green' -in $data
True
Dit kan duur worden als de lijst groot is. Ik gebruik vaak een regex-patroon als ik meer dan een paar waarden controleer.
PS> $data = @('red','green','blue')
PS> $pattern = "^({0})$" -f ($data -join '|')
PS> $pattern
^(red|green|blue)$
PS> 'green' -match $pattern
True
-eq en -ne
Gelijkheid en matrices kunnen ingewikkeld worden. Wanneer de matrix zich aan de linkerkant bevindt, wordt elk item vergeleken. In plaats van terug te keren True, wordt het object geretourneerd dat overeenkomt.
PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green
Wanneer u de -ne operator gebruikt, krijgen we alle waarden die niet gelijk zijn aan onze waarde.
PS> $data = @('red','green','blue')
PS> $data -ne 'green'
red
blue
Wanneer u dit gebruikt in een if() instructie, is een waarde die wordt geretourneerd een True waarde. Als er geen waarde wordt geretourneerd, is dit een False waarde. Beide volgende instructies evalueren.True
$data = @('red','green','blue')
if ( $data -eq 'green' )
{
'Green was found'
}
if ( $data -ne 'green' )
{
'And green was not found'
}
Ik ga hier even naar kijken als we het hebben over testen.$null
-match
De -match operator probeert elk item in de verzameling te vinden.
PS> $servers = @(
'LAX-SQL-01'
'LAX-API-01'
'ATX-SQL-01'
'ATX-API-01'
)
PS> $servers -match 'SQL'
LAX-SQL-01
ATX-SQL-01
Wanneer u met één waarde gebruikt -match , wordt een speciale variabele $Matches gevuld met overeenkomende informatie. Dit is niet het geval wanneer een matrix op deze manier wordt verwerkt.
We kunnen dezelfde aanpak gebruiken.Select-String
$servers | Select-String SQL
Ik neem Select-String-match een kijkje en de $matches variabele in een ander bericht genaamd The many ways to use regex.
$null of leeg
Het testen op $null of lege matrices kan lastig zijn. Hier volgen de algemene traps met matrices.
In één oogopslag ziet deze instructie eruit alsof deze werkt.
if ( $array -eq $null)
{
'Array is $null'
}
Maar ik heb net besproken hoe -eq elk item in de matrix wordt gecontroleerd. We kunnen dus een matrix van meerdere items hebben met één $null waarde en dit zou resulteren in $true
$array = @('one',$null,'three')
if ( $array -eq $null)
{
'I think Array is $null, but I would be wrong'
}
Daarom is het een best practice om de $null linkerkant van de operator te plaatsen. Dit maakt dit scenario een niet-probleem.
if ( $null -eq $array )
{
'Array actually is $null'
}
Een $null matrix is niet hetzelfde als een lege matrix. Als u weet dat u een matrix hebt, controleert u het aantal objecten erin. Als de matrix is $null, is 0het aantal.
if ( $array.count -gt 0 )
{
"Array isn't empty"
}
Er is nog een trap om hier op te letten. U kunt het count zelfs gebruiken als u één object hebt, tenzij dat object een PSCustomObject. Dit is een fout die is opgelost in PowerShell 6.1.
Dat is goed nieuws, maar veel mensen zijn nog steeds op 5.1 en moeten er op letten.
PS> $object = [PSCustomObject]@{Name='TestObject'}
PS> $object.count
$null
Als u nog steeds werkt met PowerShell 5.1, kunt u het object in een matrix verpakken voordat u het aantal controleert om een nauwkeurig aantal te krijgen.
if ( @($array).count -gt 0 )
{
"Array isn't empty"
}
Als u het veilig wilt afspelen, controleert u $nullop en controleert u vervolgens het aantal.
if ( $null -ne $array -and @($array).count -gt 0 )
{
"Array isn't empty"
}
All -eq
Ik heb onlangs gezien hoe iemand kan controleren of elke waarde in een matrix overeenkomt met een bepaalde waarde. Reddit-gebruiker /u/bis had deze slimme oplossing die controleert op eventuele onjuiste waarden en vervolgens het resultaat spiegelt.
$results = Test-Something
if ( -not ( $results -ne 'Passed') )
{
'All results a Passed'
}
Toevoegen aan matrices
Op dit moment vraagt u zich af hoe u items toevoegt aan een matrix. Het snelle antwoord is dat je dat niet kunt. Een matrix is een vaste grootte in het geheugen. Als u het wilt vergroten of er één item aan wilt toevoegen, moet u een nieuwe matrix maken en alle waarden uit de oude matrix kopiëren. Dit klinkt veel werk, maar PowerShell verbergt de complexiteit van het maken van de nieuwe matrix. PowerShell implementeert de opteloperator (+) voor matrices.
Notitie
PowerShell implementeert geen aftrekkingsbewerking. Als u een flexibel alternatief voor een matrix wilt, moet u een algemeen List object gebruiken.
Matrix toevoegen
We kunnen de opteloperator met matrices gebruiken om een nieuwe matrix te maken. Dus gezien deze twee matrices:
$first = @(
'Zero'
'One'
)
$second = @(
'Two'
'Three'
)
We kunnen ze samenvoegen om een nieuwe matrix te krijgen.
PS> $first + $second
Zero
One
Two
Three
Plus is gelijk aan +=
We kunnen een nieuwe matrix maken en er als volgt een item aan toevoegen:
$data = @(
'Zero'
'One'
'Two'
'Three'
)
$data += 'four'
Vergeet niet dat elke keer dat u += gebruikt dat u een nieuwe matrix dupliceert en maakt. Dit is geen probleem voor kleine gegevenssets, maar wordt zeer slecht geschaald.
Pijplijntoewijzing
U kunt de resultaten van elke pijplijn toewijzen aan een variabele. Het is een matrix als deze meerdere items bevat.
$array = 1..5 | ForEach-Object {
"ATX-SQL-$PSItem"
}
Normaal gesproken denken we aan het gebruik van de pijplijn, denken we aan de typische PowerShell-regels. We kunnen de pijplijn gebruiken met foreach() instructies en andere lussen. Dus in plaats van items toe te voegen aan een matrix in een lus, kunnen we items in de pijplijn neerzetten.
$array = foreach ( $node in (1..5))
{
"ATX-SQL-$node"
}
Matrixtypen
Standaard wordt een matrix in PowerShell gemaakt als een [PSObject[]] type. Hierdoor kan het elk type object of waarde bevatten. Dit werkt omdat alles wordt overgenomen van het PSObject type.
Sterk getypte matrices
U kunt een matrix van elk type maken met behulp van een vergelijkbare syntaxis. Wanneer u een sterk getypte matrix maakt, kan deze alleen waarden of objecten bevatten die het opgegeven type hebben.
PS> [int[]] $numbers = 1,2,3
PS> [int[]] $numbers2 = 'one','two','three'
ERROR: Cannot convert value "one" to type "System.Int32". Input string was not in a correct format."
PS> [string[]] $strings = 'one','two','three'
Matrixlijst
Het toevoegen van items aan een matrix is een van de grootste beperkingen, maar er zijn een paar andere verzamelingen die we kunnen gebruiken om dit probleem op te lossen.
Dit ArrayList is meestal een van de eerste dingen die we bedenken wanneer we een matrix nodig hebben waarmee we sneller kunnen werken. Het fungeert als een objectmatrix op elke plaats die we nodig hebben, maar het verwerkt het toevoegen van items snel.
Hier ziet u hoe we een item ArrayList maken en er items aan toevoegen.
$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')
We roepen .NET aan om dit type op te halen. In dit geval gebruiken we de standaardconstructor om deze te maken. Vervolgens roepen we de Add methode aan om er een item aan toe te voegen.
De reden waarom ik aan het begin van de regel gebruik [void] , is om de retourcode te onderdrukken. Sommige .NET-aanroepen doen dit en kunnen onverwachte uitvoer maken.
Als de enige gegevens in uw matrix tekenreeksen zijn, kunt u ook kijken naar het gebruik van StringBuilder. Het is bijna hetzelfde, maar heeft enkele methoden die alleen voor het omgaan met tekenreeksen zijn. De StringBuilder is speciaal ontworpen voor prestaties.
Het is gebruikelijk om te zien dat ArrayList mensen overstappen van matrices. Maar het komt van een tijd waarin C# geen algemene ondersteuning had. De ArrayList wordt afgeschaft ter ondersteuning van de algemene List[]
Algemene lijst
Een algemeen type is een speciaal type in C# dat een gegeneraliseerde klasse definieert en de gebruiker de gegevenstypen specificeert die worden gebruikt bij het maken. Dus als u een lijst met getallen of tekenreeksen wilt, definieert u dat u een lijst int met of string typen wilt.
U maakt als volgt een lijst voor tekenreeksen.
$mylist = [System.Collections.Generic.List[string]]::new()
Of een lijst voor getallen.
$mylist = [System.Collections.Generic.List[int]]::new()
We kunnen een bestaande matrix als volgt naar een lijst casten zonder eerst het object te maken:
$mylist = [System.Collections.Generic.List[int]]@(1,2,3)
We kunnen de syntaxis verkorten met de using namespace instructie in PowerShell 5 en hoger. De using instructie moet de eerste regel van uw script zijn. Door een naamruimte te declareren, kunt u in PowerShell deze weglaten van de gegevenstypen wanneer u ernaar verwijst.
using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)
Dit maakt het List veel bruikbaarder.
Er is een vergelijkbare Add methode beschikbaar voor u. In tegenstelling tot de matrixlijst is er geen retourwaarde voor de Add methode, zodat we dit niet hoeven te void doen.
$myList.Add(10)
En we hebben nog steeds toegang tot de elementen zoals andere matrices.
PS> $myList[-1]
10
List[PSObject]
U kunt een lijst met elk type hebben, maar wanneer u het type objecten niet kent, kunt u deze gebruiken [List[PSObject]] om ze te bevatten.
$list = [List[PSObject]]::new()
Remove()
Zowel de ArrayList algemene als de algemene List[] ondersteuning voor het verwijderen van items uit de verzameling.
using namespace System.Collections.Generic
$myList = [List[string]]@('Zero','One','Two','Three')
[void]$myList.Remove("Two")
Zero
One
Three
Wanneer u met waardetypen werkt, wordt de eerste uit de lijst verwijderd. U kunt deze steeds opnieuw aanroepen om die waarde te blijven verwijderen. Als u verwijzingstypen hebt, moet u het object opgeven dat u wilt verwijderen.
[list[System.Management.Automation.PSDriveInfo]]$drives = Get-PSDrive
$drives.remove($drives[2])
$delete = $drives[2]
$drives.remove($delete)
De verwijdermethode retourneert true of het item uit de verzameling kan worden gevonden en verwijderd.
Meer verzamelingen
Er zijn veel andere verzamelingen die kunnen worden gebruikt, maar dit zijn de goede algemene matrixvervangingen. Als u meer wilt weten over deze opties, bekijkt u deze Gist die Mark Kraus heeft samengesteld.
Andere nuances
Nu ik alle belangrijke functies heb behandeld, zijn er nog een paar dingen die ik wilde vermelden voordat ik dit oppak.
Matrices vooraf geprogrammeerd
Ik heb gezegd dat u de grootte van een matrix niet kunt wijzigen zodra deze is gemaakt. We kunnen een matrix van een vooraf bepaalde grootte maken door deze aan te roepen met de new($size) constructor.
$data = [Object[]]::new(4)
$data.count
4
Matrices vermenigvuldigen
Een interessante kleine truc is dat u een matrix kunt vermenigvuldigen met een geheel getal.
PS> $data = @('red','green','blue')
PS> $data * 3
red
green
blue
red
green
blue
red
green
blue
Initialiseren met 0
Een veelvoorkomend scenario is dat u een matrix met alle nullen wilt maken. Als u alleen gehele getallen wilt hebben, wordt een sterk getypte matrix met gehele getallen standaard ingesteld op alle nullen.
PS> [int[]]::new(4)
0
0
0
0
We kunnen ook de vermenigvuldigings truc gebruiken om dit te doen.
PS> $data = @(0) * 4
PS> $data
0
0
0
0
Het leuke aan de vermenigvuldigings truc is dat je elke waarde kunt gebruiken. Dus als u liever als uw standaardwaarde zou hebben 255 , zou dit een goede manier zijn om dit te doen.
PS> $data = @(255) * 4
PS> $data
255
255
255
255
Geneste matrices
Een matrix in een matrix wordt een geneste matrix genoemd. Ik gebruik deze niet veel in PowerShell, maar ik heb ze meer in andere talen gebruikt. Overweeg een matrix met matrices te gebruiken wanneer uw gegevens in een raster als patroon passen.
Hier volgen twee manieren waarop we een tweedimensionale matrix kunnen maken.
$data = @(@(1,2,3),@(4,5,6),@(7,8,9))
$data2 = @(
@(1,2,3),
@(4,5,6),
@(7,8,9)
)
De komma is erg belangrijk in deze voorbeelden. Ik heb een eerder voorbeeld gegeven van een normale matrix op meerdere regels waarbij de komma optioneel was. Dat is niet het geval met een multidimensionale matrix.
De manier waarop we de index notatie gebruiken, verandert iets nu we een geneste matrix hebben. Met behulp van het $data bovenstaande hebben we toegang tot de waarde 3.
PS> $outside = 0
PS> $inside = 2
PS> $data[$outside][$inside]
3
Voeg een set haakjes toe voor elk niveau van matrix genest. De eerste set vierkante haken is voor de buitenste matrix en vervolgens werkt u daar uw weg naar binnen.
Write-Output -NoEnumerate
PowerShell wil matrices uitpakken of opsommen. Dit is een belangrijk aspect van de manier waarop PowerShell gebruikmaakt van de pijplijn, maar er zijn tijden dat u dat niet wilt.
Ik sluis objecten vaak om Get-Member meer te weten te komen over deze objecten. Wanneer ik een matrix doorsluis, wordt deze uitgepakt en Get-Member de leden van de matrix en niet de werkelijke matrix ziet.
PS> $data = @('red','green','blue')
PS> $data | Get-Member
TypeName: System.String
...
Als u wilt voorkomen dat de matrix wordt uitpakt, kunt u deze gebruiken Write-Output -NoEnumerate.
PS> Write-Output -NoEnumerate $data | Get-Member
TypeName: System.Object[]
...
Ik heb een tweede manier die meer van een hack is (en ik probeer hacks als dit te vermijden). U kunt een komma voor de matrix plaatsen voordat u deze doorsluist.
PS> ,$data | Get-Member
TypeName: System.Object[]
...
Een matrix retourneren
Deze uitpakken van matrices gebeurt ook wanneer u waarden van een functie uitvoert of retourneert. U kunt nog steeds een matrix ophalen als u de uitvoer toewijst aan een variabele, zodat dit niet vaak een probleem is.
De vangst is dat u een nieuwe matrix hebt. Als dat ooit een probleem is, kunt u dit gebruiken Write-Output -NoEnumerate $array of return ,$array omzeilen.
Nog iets?
Ik weet dat dit allemaal veel is om in te nemen. Ik hoop dat u iets uit dit artikel leert telkens wanneer u het leest en dat het een goede referentie voor u blijkt te zijn voor een lange tijd. Als u dit nuttig vindt, kunt u het delen met anderen waarvan u denkt dat u er waarde uit kunt halen.
Van hieruit zou ik u aanraden een vergelijkbaar bericht te bekijken dat ik heb geschreven over hashtables.