Delen via


Alles wat u wilde 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 het blog dat is 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 begin met een eenvoudige technische beschrijving van wat matrices zijn en hoe ze worden gebruikt door de meeste programmeertalen voordat ik naar de andere manieren ga 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 sequentiële chquentiële hoeveelheid geheugen waarin elke waarde naast de andere waarde wordt opgeslagen.

Ik zal elk van die details aanraken terwijl we gaan.

Basaal gebruik

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 deze met waarden zaaien door ze @() tussen haakjes te plaatsen.

PS> $data = @('Zero','One','Two','Three')
PS> $data.count
4

PS> $data
Zero
One
Two
Three

Deze matrix heeft 4 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 wordt over het algemeen weggelaten.

$data = @(
    'Zero'
    'One'
    'Two'
    'Three'
)

Ik declareer liever mijn matrices op meerdere regels als dat. Het wordt niet alleen gemakkelijker te lezen wanneer u meerdere items hebt, maar het maakt het ook gemakkelijker om te vergelijken met eerdere versies bij het gebruik van broncodebeheer.

Andere syntaxis

Dit is meestal @() de syntaxis voor het maken van een matrix, maar door komma's gescheiden lijsten werken meestal.

$data = 'Zero','One','Two','Three'

Write-Output voor het maken van matrices

Een handige truc die het vermelden waard is, is dat u kunt gebruiken Write-Output om snel tekenreeksen te 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 met items erin hebt, kunt u deze items openen en bijwerken.

Verschuiving

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 offset van 0 items gebruiken om ernaar te komen. Om naar het tweede item te gaan, moeten we een offset van 1 gebruiken om het eerste item over te slaan.

PS> $data[1]
One

Dit betekent dat het laatste item zich op offset 3 bevindt.

PS> $data[3]
Three

Index

U kunt nu zien waarom ik de waarden heb gekozen die ik voor dit voorbeeld heb gedaan. Ik heb dit geïntroduceerd als een offset omdat dat is wat het echt is, maar deze offset 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 de 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 dit gebruiken -1.

PS> $data[-1]
Three

Een woord van voorzichtigheid hier met de .. operator. De volgorde 0..-1 en -1..0 evaluatie van de waarden 0,-1 en -1,0. Het is gemakkelijk te zien $data[0..-1] en te denken dat het alle items opsommen 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 bepaald 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.

Tellen

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 eigenschap retourneert 0.

PS> $null.count
0

Er zijn hier enkele traps die ik opnieuw zal bekijken wanneer ik de controle $null op of lege matrices verderop in dit artikel bedek.

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 mentaal te denken dat u het tweede item wilt en een index gebruikt van 2 en echt het derde item krijgt. Of door te denken dat u vier items hebt en u het laatste item wilt, dus u gebruikt het aantal voor toegang tot het laatste item.

$data[ $data.count ]

PowerShell is perfect om dat te doen en u precies te geven welk item er bestaat op index 4: $null. U moet het bovenstaande gebruiken $data.count - 1 of de -1 informatie die we hierboven hebben geleerd.

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 maximum indexnummer te verkrijgen.

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 naar kijken als we praten 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 ga later verder 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 bedoeld voor elkaar. 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 nog niet eerder hebt gezien $PSItem , weet je gewoon dat het hetzelfde is als $_. U kunt een van beide gebruiken omdat ze beide het huidige object in de pijplijn vertegenwoordigen.

ForEach-lus

De ForEach lus werkt goed met verzamelingen. De syntaxis gebruiken: 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 neemt een parameter die een scriptblok is. 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 veel gebruikt in de meeste andere talen, maar u ziet deze niet veel in PowerShell. Wanneer u dit wel 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 aan 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 we de index moeten verhogen met 1. In dit geval $index++ staat voor $index = $index + 1. De notatieoperator (-f) wordt gebruikt om de waarde van $data[$index] in 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 gemakkelijk om de voorwaarde enigszins verkeerd te krijgen om een fout met één fout in uw logica op te halen. Het gebruik $index -le $data.count van of $index -lt ($data.count - 1) zijn ooit zo fout. Hierdoor wordt 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 deze 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 dat 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 die we al hebben besproken, 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 inventariseert ze allemaal voor ons en retourneert een schone lijst.

PS> $data.LastName

Marquette
Doe

De opsomming gebeurt nog steeds, maar we zien de complexiteit erachter niet.

Waar-objectfiltering

Hier komt Where-Object u binnen, 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 in lussen bijwerken

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.

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 meer 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.

-verbinden

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 mij aanwees. Als u ooit alles zonder scheidingsteken wilt samenvoegen, in plaats van dit te doen:

PS> $data = @(1,2,3,4)
PS> $data -join $null
1234

U kunt met de matrix als parameter zonder voorvoegsel gebruiken -join . Bekijk dit voorbeeld om te zien waar ik het over heb.

PS> $data = @(1,2,3,4)
PS> -join $data
1234

-replace en -split

De andere operators vinden het -replace leuk en -split worden uitgevoerd op elk item in de matrix. 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 in een if() instructie gebruikt, is een waarde die wordt geretourneerd een True waarde. Als er geen waarde wordt geretourneerd, is dit een False waarde. Beide volgende instructies worden geëvalueerd.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 voor $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 gegevens. Dit is niet het geval wanneer een matrix op deze manier wordt verwerkt.

We kunnen dezelfde aanpak hanteren met Select-String.

$servers | Select-String SQL

Ik neem een kijkje Select-String-match en de $matches variabele in een ander bericht genaamd De vele manieren om regex te gebruiken.

$null of leeg

Testen op $null of lege matrices kan lastig zijn. Hier volgen de veelvoorkomende traps met matrices.

In één oogopslag ziet deze instructie eruit alsof deze werkt.

if ( $array -eq $null)
{
    'Array is $null'
}

Maar ik heb net aangegeven hoe -eq elk item in de matrix wordt gecontroleerd. We kunnen dus een matrix van meerdere items met één $null waarde hebben 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 val 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 erop letten.

PS> $object = [PSCustomObject]@{Name='TestObject'}
PS> $object.count
$null

Als u nog steeds powerShell 5.1 gebruikt, kunt u het object in een matrix verpakken voordat u het aantal controleert om een nauwkeurig aantal te verkrijgen.

if ( @($array).count -gt 0 )
{
    "Array isn't empty"
}

Als u het volledig wilt afspelen, controleert u op $nullen controleert u vervolgens het aantal.

if ( $null -ne $array -and @($array).count -gt 0 )
{
    "Array isn't empty"
}

All -eq

Ik heb onlangs iemand op Reddit gezien hoe ik kan controleren of elke waarde in een matrix overeenkomt met een bepaalde waarde. Reddit-gebruiker u/bis had deze slimme oplossing die controleert op 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 als veel werk, maar PowerShell verbergt de complexiteit van het maken van de nieuwe matrix. PowerShell implementeert de optellingsoperator (+) 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 operator voor optellen 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 op te halen.

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'

Onthoud dat telkens wanneer u gebruikt += dat u een nieuwe matrix dupliceert en maakt. Dit is geen probleem voor kleine gegevenssets, maar het schaalt zeer slecht.

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-one-liners. 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'

ArrayList

Het toevoegen van items aan een matrix is een van de grootste beperkingen, maar er zijn enkele andere verzamelingen die we kunnen omzetten 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 u een ArrayList item maakt en hieraan toevoegt.

$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 die u in uw matrix hebt, tekenreeksen zijn, bekijkt u ook het gebruik van StringBuilder. Het is bijna hetzelfde, maar heeft een aantal methoden die alleen voor het omgaan met tekenreeksen zijn. De StringBuilder is speciaal ontworpen voor prestaties.

Het is gebruikelijk om te zien dat mensen overstappen ArrayList van matrices. Maar het komt van een tijd waarin C# geen algemene ondersteuning had. De ArrayList is 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 met int 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 deze uit de gegevenstypen laten wanneer u ernaar verwijst.

using namespace System.Collections.Generic
$myList = [List[int]]@(1,2,3)

Dit maakt het List veel bruikbaarder.

U hebt een vergelijkbare Add methode die voor u beschikbaar is. In tegenstelling tot de matrixlijst is er geen retourwaarde voor de Add methode, zodat we dit niet hoeven te doen void .

$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 weet, kunt u deze gebruiken [List[PSObject]] om ze te bevatten.

$list = [List[PSObject]]::new()

Remove()

De ArrayList en de algemene beide List[] ondersteunen 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 als het item kan worden gevonden en verwijderd uit de verzameling.

Meer verzamelingen

Er zijn veel andere verzamelingen die kunnen worden gebruikt, maar dit zijn de goede algemene matrixvervangingen. Als u meer van deze opties wilt leren, bekijkt u deze Gist die Mark Kraus heeft samengesteld.

Andere nuances

Nu ik alle belangrijke functionaliteit heb behandeld, zijn er nog een paar dingen die ik wilde vermelden voordat ik dit inpak.

Matrices vooraf aanpassen

Ik heb gezegd dat u de grootte van een matrix niet kunt wijzigen nadat 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 hebt, 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 om een matrix van matrices te gebruiken wanneer uw gegevens in een raster passen zoals een patroon.

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 bij 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 weg.

Write-Output -NoEnumerate

PowerShell wil matrices uitpakken of opsommen. Dit is een belangrijk aspect van de manier waarop PowerShell de pijplijn gebruikt, maar soms wilt u dat niet doen.

Ik sluis objecten vaak door om Get-Member meer te weten te komen over deze objecten. Wanneer ik een matrix doorsluis, wordt deze uitgepakt en ziet Get-Member de leden van de matrix en niet de werkelijke matrix.

PS> $data = @('red','green','blue')
PS> $data | Get-Member
TypeName: System.String
...

Als u wilt voorkomen dat de matrix wordt uitpakt, kunt u dit gebruiken Write-Output -NoEnumerate.

PS> Write-Output -NoEnumerate $data | Get-Member
TypeName: System.Object[]
...

Ik heb een tweede manier dat is meer van een hack (en ik probeer hacks als dit te vermijden). U kunt een komma vóór de matrix plaatsen voordat u deze doorsluist. Dit loopt terug $data in een andere matrix waar dit het enige element is, dus na het uitpakken van de buitenste matrix worden we weer $data uitgepakt.

PS> ,$data | Get-Member
TypeName: System.Object[]
...

Een matrix retourneren

Dit 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 aan een variabele toewijst, zodat dit meestal geen 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. Mijn hoop is 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 vond, kunt u het delen met anderen waarvan u denkt dat u er waarde uit haalt.

Vanaf hier zou ik u aanraden om een soortgelijk bericht te bekijken dat ik heb geschreven over hashtables.