Allt du ville veta om matriserEverything you wanted to know about arrays

Matriser är en grundläggande språk funktion för de flesta programmeringsspråk.Arrays are a fundamental language feature of most programming languages. De är en samling med värden eller objekt som är svåra att undvika.They're a collection of values or objects that are difficult to avoid. Låt oss ta en närmare titt på matriser och allt de behöver för att erbjuda.Let's take a close look at arrays and everything they have to offer.

Anteckning

Den [ursprungliga versionen][] av den här artikeln visas på bloggen som skrivits av @KevinMarquette .The original version of this article appeared on the blog written by @KevinMarquette. PowerShell-teamet tackar för att dela det här innehållet med oss.The PowerShell team thanks Kevin for sharing this content with us. Ta en titt på hans blogg på PowerShellExplained.com.Please check out his blog at PowerShellExplained.com.

Vad är en matris?What is an array?

Jag ska börja med en grundläggande teknisk beskrivning av vilka matriser som är och hur de används av de flesta programmeringsspråk innan jag växlar till andra sätt som PowerShell använder dem.I'm going to start with a basic technical description of what arrays are and how they are used by most programming languages before I shift into the other ways PowerShell makes use of them.

En matris är en data struktur som fungerar som en samling av flera objekt.An array is a data structure that serves as a collection of multiple items. Du kan iterera över matrisen eller komma åt enskilda objekt med ett index.You can iterate over the array or access individual items using an index. Matrisen skapas som ett sekventiellt segment av minne där varje värde lagras direkt bredvid det andra.The array is created as a sequential chunk of memory where each value is stored right next to the other.

Jag tittar på var och en av de här detaljerna.I'll touch on each of those details as we go.

Grundläggande användningBasic usage

Eftersom matriser är en sådan grundläggande funktion i PowerShell finns det en enkel syntax för att arbeta med dem i PowerShell.Because arrays are such a basic feature of PowerShell, there is a simple syntax for working with them in PowerShell.

Skapa en matrisCreate an array

En tom matris kan skapas med hjälp av @()An empty array can be created by using @()

PS> $data = @()
PS> $data.count
0

Vi kan skapa en matris och dirigera den med värden genom att placera dem inom @() parentesen.We can create an array and seed it with values just by placing them in the @() parentheses.

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

PS> $data
Zero
One
Two
Three

Den här matrisen innehåller 4 objekt.This array has 4 items. När vi kallar $data variabeln visas en lista över våra objekt.When we call the $data variable, we see the list of our items. Om det är en sträng mat ris, får vi en rad per sträng.If it's an array of strings, then we get one line per string.

Vi kan deklarera en matris på flera rader.We can declare an array on multiple lines. Kommatecken är valfri i det här fallet och skrivs vanligt vis ut.The comma is optional in this case and generally left out.

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

Jag vill deklarera mina matriser på flera rader som.I prefer to declare my arrays on multiple lines like that. Det blir inte bara lättare att läsa när du har flera objekt, men det gör det också enklare att jämföra med tidigare versioner när du använder käll kontroll.Not only does it get easier to read when you have multiple items, it also makes it easier to compare to previous versions when using source control.

Annan syntaxOther syntax

Det är vanligt att du @() använder syntaxen för att skapa en matris, men i kommaavgränsade listor fungerar det mesta av tiden.It's commonly understood that @() is the syntax for creating an array, but comma-separated lists work most of the time.

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

Write-Output för att skapa matriserWrite-Output to create arrays

Ett häftigt svårt att nämna är att du kan använda Write-Output för att snabbt skapa strängar i-konsolen.One cool little trick worth mentioning is that you can use Write-Output to quickly create strings at the console.

$data = Write-Output Zero One Two Three

Detta är praktiskt eftersom du inte behöver ange citat tecken runt strängarna när parametern accepterar strängar.This is handy because you don't have to put quotes around the strings when the parameter accepts strings. Jag skulle aldrig göra detta i ett skript, men det är ett rättvist spel i-konsolen.I would never do this in a script but it's fair game in the console.

Åtkomst till objektAccessing items

Nu när du har en matris med objekt i den, kanske du vill komma åt och uppdatera dessa objekt.Now that you have an array with items in it, you may want to access and update those items.

OffsetOffset

För att få åtkomst till enskilda objekt använder vi hakparenteserna [] med ett förskjutnings värde som börjar vid 0.To access individual items, we use the brackets [] with an offset value starting at 0. Så här får vi det första objektet i vår matris:This is how we get the first item in our array:

PS> $data = 'Zero','One','Two','Three'
PS> $data[0]
Zero

Anledningen till varför vi använder noll här är att det första objektet är i början av listan, så vi använder en förskjutning på 0 objekt för att komma till den.The reason why we use zero here is because the first item is at the beginning of the list so we use an offset of 0 items to get to it. För att komma till det andra objektet måste vi använda en förskjutning på 1 för att hoppa över det första objektet.To get to the second item, we would need to use an offset of 1 to skip the first item.

PS> $data[1]
One

Detta innebär att det sista objektet finns vid förskjutning 3.This would mean that the last item is at offset 3.

PS> $data[3]
Three

IndexIndex

Nu kan du se varför jag har valt de värden som jag gjorde för det här exemplet.Now you can see why I picked the values that I did for this example. Jag introducerade detta som en förskjutning eftersom det är det som är det som egentligen är, men den här förskjutningen kallas ofta för ett index.I introduced this as an offset because that is what it really is, but this offset is more commonly referred to as an index. Ett index som startar vid 0 .An index that starts at 0. För resten av den här artikeln anropar du förskjutningen av ett index.For the rest of this article I will call the offset an index.

Särskilda index trickSpecial index tricks

På de flesta språk kan du bara ange ett enda tal som index och få ett enda objekt tillbaka.In most languages, you can only specify a single number as the index and you get a single item back. PowerShell är mycket mer flexibelt.PowerShell is much more flexible. Du kan använda flera index samtidigt.You can use multiple indexes at once. Genom att tillhandahålla en lista över index kan vi välja flera objekt.By providing a list of indexes, we can select several items.

PS> $data[0,2,3]
Zero
Two
Three

Objekten returneras baserat på ordningen på de index som tillhandahålls.The items are returned based on the order of the indexes provided. Om du duplicerar ett index får du objektet båda gånger.If you duplicate an index, you get that item both times.

PS> $data[3,0,3]
Three
Zero
Three

Vi kan ange en sekvens med siffror med den inbyggda .. operatorn.We can specify a sequence of numbers with the built-in .. operator.

PS> $data[1..3]
One
Two
Three

Detta fungerar även i omvänd ordning.This works in reverse too.

PS> $data[3..1]
Three
Two
One

Du kan använda negativa index värden för att räkna från slutet.You can use negative index values to offset from the end. Så om du behöver det sista objektet i listan kan du använda -1 .So if you need the last item in the list, you can use -1.

PS> $data[-1]
Three

Ett ord med varnings meddelande här med .. operatorn.One word of caution here with the .. operator. Sekvensen 0..-1 och -1..0 utvärdera till värdena 0,-1 och -1,0 .The sequence 0..-1 and -1..0 evaluate to the values 0,-1 and -1,0. Det är enkelt att se $data[0..-1] och fundera på att räkna upp alla objekt om du glömmer den här informationen.It's easy to see $data[0..-1] and think it would enumerate all items if you forget this detail. $data[0..-1] ger dig samma värde som när $data[0,-1] du ger det första och sista objektet i matrisen (och inget av de andra värdena).$data[0..-1] gives you the same value as $data[0,-1] by giving you the first and last item in the array (and none of the other values).

Utanför intervalletOut of bounds

Om du försöker komma åt ett index för ett objekt som är i slutet av matrisen på de flesta språk får du någon typ av fel eller ett undantag.In most languages, if you try to access an index of an item that is past the end of the array, you would get some type of error or an exception. PowerShell returnerar ingenting i tysthet.PowerShell silently returns nothing.

PS> $null -eq $data[9000]
True

Det går inte att indexera till en null-matrisCannot index into a null array

Om din variabel är $null och du försöker indexera den som en matris får du ett System.Management.Automation.RuntimeException undantag med meddelandet Cannot index into a null array .If your variable is $null and you try to index it like an array, you get a System.Management.Automation.RuntimeException exception with the message Cannot index into a null array.

PS> $empty = $null
SP> $empty[0]
Error: Cannot index into a null array.

Se därför till att matriserna inte är $null innan du försöker komma åt element i dem.So make sure your arrays are not $null before you try to access elements inside them.

AntalCount

Matriser och andra samlingar har en Count-egenskap som visar hur många objekt som finns i matrisen.Arrays and other collections have a count property that tells you how many items are in the array.

PS> $data.count
4

PowerShell 3,0 har lagt till en Count-egenskap på de flesta objekt.PowerShell 3.0 added a count property to most objects. Du kan ha ett enda objekt och det bör ge dig ett antal 1 .you can have a single object and it should give you a count of 1.

PS> $date = Get-Date
PS> $date.count
1

$nullDet finns även en Count-egenskap förutom den returnerar 0 .Even $null has a count property except it returns 0.

PS> $null.count
0

Det finns vissa traps som jag ska gå tillbaka när jag söker efter $null eller tomma matriser senare i den här artikeln.There are some traps here that I will revisit when I cover checking for $null or empty arrays later on in this article.

Av-ett felOff-by-one errors

Ett vanligt programmerings fel har skapats eftersom matriser börjar vid index 0.A common programming error is created because arrays start at index 0. Andra fel kan införas på två sätt.Off-by-one errors can be introduced in two ways.

Det första är att tänka på att du vill ha det andra objektet och använda ett index för 2 och verkligen hämtar det tredje objektet.The first is by mentally thinking you want the second item and using an index of 2 and really getting the third item. Eller genom att fundera på att du har fyra objekt och du vill ha det sista objektet så använder du antalet för att komma åt det sista objektet.Or by thinking that you have four items and you want last item, so you use the count to access the last item.

$data[ $data.count ]

PowerShell är perfekt glad att låta dig göra det och ge dig exakt det objekt som finns vid index 4: $null .PowerShell is perfectly happy to let you do that and give you exactly what item exists at index 4: $null. Du bör använda $data.count - 1 eller det -1 som vi har lärt dig ovan.You should be using $data.count - 1 or the -1 that we learned about above.

PS> $data[ $data.count - 1 ]
Three

Det är här du kan använda -1 indexet för att hämta det sista elementet.This is where you can use the -1 index to get the last element.

PS> $data[ -1 ]
Three

Pettersson Dailey pekar också ut till mig som vi kan använda $data.GetUpperBound(0) för att hämta det högsta index numret.Lee Dailey also pointed out to me that we can use $data.GetUpperBound(0) to get the max index number.

PS> $data.GetUpperBound(0)
3
PS> $data[ $data.GetUpperBound(0) ]
Three

Det andra vanligaste sättet är när du går igenom listan och inte stoppar vid rätt tidpunkt.The second most common way is when iterating the list and not stopping at the right time. Jag går igenom detta när vi pratar om att använda for slingan.I'll revisit this when we talk about using the for loop.

Uppdaterar objektUpdating items

Vi kan använda samma index för att uppdatera befintliga objekt i matrisen.We can use the same index to update existing items in the array. Detta ger oss direkt åtkomst till uppdatering av enskilda objekt.This gives us direct access to update individual items.

$data[2] = 'dos'
$data[3] = 'tres'

Om vi försöker uppdatera ett objekt som har passerat det sista elementet får vi ett Index was outside the bounds of the array. fel meddelande.If we try to update an item that is past the last element, then we get an Index was outside the bounds of the array. error.

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

Jag går tillbaka senare när jag pratar om hur man gör en matris större.I'll revisit this later when I talk about how to make an array larger.

IterationIteration

Ibland kan du behöva gå igenom hela listan och utföra en åtgärd för varje objekt i matrisen.At some point, you might need to walk or iterate the entire list and perform some action for each item in the array.

PipelinePipeline

Matriser och PowerShell-pipeline är avsedda för varandra.Arrays and the PowerShell pipeline are meant for each other. Detta är ett av de enklaste sätten att bearbeta dessa värden.This is one of the simplest ways to process over those values. När du skickar en matris till en pipeline bearbetas varje objekt i matrisen separat.When you pass an array to a pipeline, each item inside the array is processed individually.

PS> $data = 'Zero','One','Two','Three'
PS> $data | ForEach-Object {"Item: [$PSItem]"}
Item: [Zero]
Item: [One]
Item: [Two]
Item: [Three]

Om du inte har sett $PSItem tidigare vet du att det är samma sak som $_ .If you have not seen $PSItem before, just know that it's the same thing as $_. Du kan använda antingen en, eftersom de båda representerar det aktuella objektet i pipelinen.You can use either one because they both represent the current object in the pipeline.

Förgrunds slingaForEach loop

ForEachSlingan fungerar bra med samlingar.The ForEach loop works well with collections. Använda syntaxen: foreach ( <variable> in <collection> )Using the syntax: foreach ( <variable> in <collection> )

foreach ( $node in $data )
{
    "Item: [$node]"
}

Förgrunds metodForEach method

Jag vill glömma bort det här, men det fungerar bra för enkla åtgärder.I tend to forget about this one but it works well for simple operations. Med PowerShell kan du anropa .ForEach() en samling.PowerShell allows you to call .ForEach() on a collection.

PS> $data.foreach({"Item [$PSItem]"})
Item [Zero]
Item [One]
Item [Two]
Item [Three]

.foreach()Tar en parameter som är ett skript block.The .foreach() takes a parameter that is a script block. Du kan ta bort parenteserna och bara ange skript blocket.You can drop the parentheses and just provide the script block.

$data.foreach{"Item [$PSItem]"}

Detta är en mindre känd syntax, men den fungerar precis på samma sätt.This is a lesser known syntax but it works just the same. Den här foreach metoden har lagts till i PowerShell 4,0.This foreach method was added in PowerShell 4.0.

For-loopFor loop

forSlingan används kraftigt på de flesta andra språk, men du ser det inte mycket i PowerShell.The for loop is used heavily in most other languages but you don't see it much in PowerShell. När du gör det är det ofta i sammanhanget att gå en matris.When you do see it, it's often in the context of walking an array.

for ( $index = 0; $index -lt $data.count; $index++)
{
    "Item: [{0}]" -f $data[$index]
}

Det första vi gör är att initiera en $index till 0 .The first thing we do is initialize an $index to 0. Sedan lägger vi till villkoret som $index måste vara mindre än $data.count .Then we add the condition that $index must be less than $data.count. Slutligen anger vi att det ska gå att öka indexet genom att varje gång vi loopar 1 .Finally, we specify that every time we loop that me must increase the index by 1. I det här fallet $index++ är det kort för $index = $index + 1 .In this case $index++ is short for $index = $index + 1.

När du använder en for slinga bör du ägna särskild uppmärksamhet åt villkoret.Whenever you're using a for loop, pay special attention to the condition. Jag använde $index -lt $data.count detta.I used $index -lt $data.count here. Det är enkelt att få tillståndet något fel för att få ett fel i din logik.It's easy to get the condition slightly wrong to get an off-by-one error in your logic. $index -le $data.count $index -lt ($data.count - 1) Det kan vara något fel att använda eller.Using $index -le $data.count or $index -lt ($data.count - 1) are ever so slightly wrong. Detta skulle leda till att du bearbetar för många eller för få objekt.That would cause your result to process too many or too few items. Detta är det klassiska fel meddelandet.This is the classic off-by-one error.

Växel slingaSwitch loop

Det här är en som är lätt att förbise.This is one that is easy to overlook. Om du anger en matris till en switch-instruktion, kontrollerar den varje objekt i matrisen.If you provide an array to a switch statement, it checks each item in the array.

$data = 'Zero','One','Two','Three'
switch( $data )
{
    'One'
    {
        'Tock'
    }
    'Three'
    {
        'Tock'
    }
    Default
    {
        'Tick'
    }
}
Tick
Tock
Tick
Tock

Det finns många häftiga saker som vi kan göra med Switch-instruktionen.There are a lot of cool things that we can do with the switch statement. Jag har en annan artikel som är engagerad i detta.I have another article dedicated to this.

Uppdaterar värdenUpdating values

Om matrisen är en samling strängar eller heltal (värde typer) kan ibland det hända att du vill uppdatera värdena i matrisen när du loopar.When your array is a collection of string or integers (value types), sometimes you may want to update the values in the array as you loop over them. De flesta av slingarna ovan använder en variabel i slingan som innehåller en kopia av värdet.Most of the loops above use a variable in the loop that holds a copy of the value. Om du uppdaterar variabeln, uppdateras inte det ursprungliga värdet i matrisen.If you update that variable, the original value in the array is not updated.

Undantaget till den instruktionen är for slingan.The exception to that statement is the for loop. Om du vill visa en matris och uppdatera värden inuti den, for är loopen det du söker.If you want to walk an array and update values inside it, then the for loop is what you're looking for.

for ( $index = 0; $index -lt $data.count; $index++ )
{
    $data[$index] = "Item: [{0}]" -f $data[$index]
}

Det här exemplet tar ett värde av indexet, gör några ändringar och använder sedan samma index för att tilldela det igen.This example takes a value by index, makes a few changes, and then uses that same index to assign it back.

Matriser med objektArrays of Objects

Hittills har vi placerat i en matris som värde typ, men matriser kan också innehålla objekt.So far, the only thing we've placed in an array is a value type, but arrays can also contain objects.

$data = @(
    [pscustomobject]@{FirstName='Kevin';LastName='Marquette'}
    [pscustomobject]@{FirstName='John'; LastName='Doe'}
)

Många cmdlets returnerar samlingar av objekt som matriser när du tilldelar dem till en variabel.Many cmdlets return collections of objects as arrays when you assign them to a variable.

$processList = Get-Process

Alla grundläggande funktioner som vi redan har talat om fortfarande gäller för matriser med objekt med lite information som pekar på.All of the basic features we already talked about still apply to arrays of objects with a few details worth pointing out.

Åtkomst till egenskaperAccessing properties

Vi kan använda ett index för att komma åt ett enskilt objekt i en samling, precis som med värde typerna.We can use an index to access an individual item in a collection just like with value types.

PS> $data[0]

FirstName LastName
-----     ----
Kevin     Marquette

Vi kan komma åt och uppdatera egenskaper direkt.We can access and update properties directly.

PS> $data[0].FirstName

Kevin

PS> $data[0].FirstName = 'Jay'
PS> $data[0]

FirstName LastName
-----     ----
Jay       Marquette

Mat ris egenskaperArray properties

Normalt skulle du behöva räkna upp hela listan som detta för att få åtkomst till alla egenskaper:Normally you would have to enumerate the whole list like this to access all the properties:

PS> $data | ForEach-Object {$_.LastName}

Marquette
Doe

Eller med hjälp av Select-Object -ExpandProperty cmdleten.Or by using the Select-Object -ExpandProperty cmdlet.

PS> $data | Select-Object -ExpandProperty LastName

Marquette
Doe

Men PowerShell ger oss möjlighet att begära LastName direkt.But PowerShell offers us the ability to request LastName directly. PowerShell räknar upp dem för oss och returnerar en rensad lista.PowerShell enumerates them all for us and returns a clean list.

PS> $data.LastName

Marquette
Doe

Uppräkningen utförs fortfarande men vi ser inte komplexiteten bakom den.The enumeration still happens but we don't see the complexity behind it.

Where-Object filtreringWhere-Object filtering

Where-ObjectI så fall kan vi filtrera och välja vad du vill ha i matrisen baserat på egenskaperna för objektet.This is where Where-Object comes in so we can filter and select what we want out of the array based on the properties of the object.

PS> $data | Where-Object {$_.FirstName -eq 'Kevin'}

FirstName LastName
-----     ----
Kevin     Marquette

Vi kan skriva samma fråga för att få din FirstName sökning.We can write that same query to get the FirstName we are looking for.

$data | Where FirstName -eq Kevin

Where ()Where()

Matriser har en Where() metod för dem som gör att du kan ange en scriptblock för filtret.Arrays have a Where() method on them that allows you to specify a scriptblock for the filter.

$data.Where({$_.FirstName -eq 'Kevin'})

Den här funktionen lades till i PowerShell 4,0.This feature was added in PowerShell 4.0.

Uppdatera objekt i slingorUpdating objects in loops

Med värde typer är det enda sättet att uppdatera matrisen att använda en for-loop eftersom vi måste känna till indexet för att ersätta värdet.With value types, the only way to update the array is to use a for loop because we need to know the index to replace the value. Vi har fler alternativ med objekt eftersom de är referens typer.We have more options with objects because they are reference types. Här är ett snabbt exempel:Here is a quick example:

foreach($person in $data)
{
    $person.FirstName = 'Kevin'
}

Den här slingen går igenom varje objekt i $data matrisen.This loop is walking every object in the $data array. Eftersom objekt är referens typer $person refererar variabeln exakt samma objekt som finns i matrisen.Because objects are reference types, the $person variable references the exact same object that is in the array. Så uppdateringar av dess egenskaper uppdaterar du originalet.So updates to its properties do update the original.

Du kan fortfarande inte ersätta hela objektet på det här sättet.You still can't replace the whole object this way. Om du försöker tilldela ett nytt objekt till $person variabeln uppdaterar du variabel referensen till något annat som inte längre pekar på det ursprungliga objektet i matrisen.If you try to assign a new object to the $person variable, you're updating the variable reference to something else that no longer points to the original object in the array. Detta fungerar som du förväntar dig:This doesn't work like you would expect:

foreach($person in $data)
{
    $person = [pscustomobject]@{
        FirstName='Kevin'
        LastName='Marquette'
    }
}

OperatorerOperators

Operatorerna i PowerShell fungerar också på matriser.The operators in PowerShell also work on arrays. Några av dem fungerar något annorlunda.Some of them work slightly differently.

– Anslut-join

-joinOperatören är den mest uppenbara, så låt oss titta på den först.The -join operator is the most obvious one so let's look at it first. Jag gillar -join operatorn och använder den ofta.I like the -join operator and use it often. Den kopplar ihop alla element i matrisen med det tecken eller den sträng som du anger.It joins all elements in the array with the character or string that you specify.

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

En av de funktioner som jag gillar om -join operatorn är att den hanterar enskilda objekt.One of the features that I like about the -join operator is that it handles single items.

PS> 1 -join '-'
1

Jag använder det här i loggnings-och utförliga meddelanden.I use this inside logging and verbose messages.

PS> $data = @(1,2,3,4)
PS> "Data is $($data -join ',')."
Data is 1,2,3,4.

– Anslut $array-join $array

Här är ett smarta-stick som Pettersson Dailey påpekade till mig.Here is a clever trick that Lee Dailey pointed out to me. I stället för att göra detta, om du vill koppla allt utan en avgränsare:If you ever want to join everything without a delimiter, instead of doing this:

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

Du kan använda -join med matrisen som parameter utan prefix.You can use -join with the array as the parameter with no prefix. Ta en titt på det här exemplet för att se att jag pratar om.Take a look at this example to see that I'm talking about.

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

-Ersätt och-dela-replace and -split

De andra operatorerna som -replace och -split körs på varje objekt i matrisen.The other operators like -replace and -split execute on each item in the array. Jag kan inte säga att jag någonsin har använt dem på det här sättet, men här är ett exempel.I can't say that I have ever used them this way but here is an example.

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

– innehåller-contains

Med -contains operatorn kan du kontrol lera en matris med värden för att se om den innehåller ett angivet värde.The -contains operator allows you to check an array of values to see if it contains a specified value.

PS> $data = @('red','green','blue')
PS> $data -contains 'green'
True

– in-in

Om du har ett enda värde som du vill verifiera matchar ett av flera värden kan du använda -in operatorn.When you have a single value that you would like to verify matches one of several values, you can use the -in operator. Värdet är till vänster och matrisen på höger sida av operatorn.The value would be on the left and the array on the right-hand side of the operator.

PS> $data = @('red','green','blue')
PS> 'green' -in $data
True

Detta kan bli dyrt om listan är stor.This can get expensive if the list is large. Jag använder ofta ett regex-mönster om jag söker efter fler än några värden.I often use a regex pattern if I'm checking more than a few values.

PS> $data = @('red','green','blue')
PS> $pattern = "^({0})$" -f ($data -join '|')
PS> $pattern
^(red|green|blue)$

PS> 'green' -match $pattern
True

-EQ och-Ne-eq and -ne

Likheter och matriser kan bli komplicerade.Equality and arrays can get complicated. När matrisen är på vänster sida jämförs varje objekt.When the array is on the left side, every item gets compared. I stället för att returnera returneras True det objekt som matchar.Instead of returning True, it returns the object that matches.

PS> $data = @('red','green','blue')
PS> $data -eq 'green'
green

När du använder -ne operatorn får vi alla värden som inte är lika med vårt värde.When you use the -ne operator, we get all the values that are not equal to our value.

PS> $data = @('red','green','blue')
PS> $data -ne 'green'
red
blue

När du använder det här i en if() instruktion är ett värde som returneras ett True värde.When you use this in an if() statement, a value that is returned is a True value. Om inget värde returneras är det ett False värde.If no value is returned, then it's a False value. Båda dessa Next-instruktioner utvärderas till True .Both of these next statements evaluate to True.

$data = @('red','green','blue')
if ( $data -eq 'green' )
{
    'Green was found'
}
if ( $data -ne 'green' )
{
    'And green was not found'
}

Jag går tillbaka så snart vi pratar om testningen av $null .I'll revisit this in a moment when we talk about testing for $null.

-matcha-match

-matchOperatorn försöker matcha varje objekt i samlingen.The -match operator tries to match each item in the collection.

PS> $servers = @(
    'LAX-SQL-01'
    'LAX-API-01'
    'ATX-SQL-01'
    'ATX-API-01'
)
PS> $servers -match 'SQL'
LAX-SQL-01
ATX-SQL-01

När du använder -match med ett enda värde fylls en speciell variabel $Matches med matchnings information.When you use -match with a single value, a special variable $Matches gets populated with match info. Detta är inte fallet när en matris behandlas på det här sättet.This isn't the case when an array is processed this way.

Vi kan utföra samma tillvägagångs sätt med Select-String .We can take the same approach with Select-String.

$servers | Select-String SQL

Jag tar en närmare titt på Select-String , -match och $matches variabeln i ett annat inlägg som kallas [för många sätt att använda regex][].I take a closer look at Select-String,-match and the $matches variable in another post called The many ways to use regex.

$null eller tomt$null or empty

$nullDet kan vara svårt att testa för eller tomma matriser.Testing for $null or empty arrays can be tricky. Här är vanliga traps med matriser.Here are the common traps with arrays.

Den här instruktionen ser ut ungefär som den ska fungera.At a glance, this statement looks like it should work.

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

Men jag gick bara igenom hur -eq kontrollerar varje objekt i matrisen.But I just went over how -eq checks each item in the array. Vi kan därför ha en matris med flera objekt med ett enda $null värde och det skulle utvärderas till $trueSo we can have an array of several items with a single $null value and it would evaluate to $true

$array = @('one',$null,'three')
if ( $array -eq $null)
{
    'I think Array is $null, but I would be wrong'
}

Det är därför det bästa sättet att placera $null på den vänstra sidan av operatören.This is why it's a best practice to place the $null on the left side of the operator. Detta gör att det här scenariot inte är ett problem.This makes this scenario a non-issue.

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

En $null matris är inte samma sak som en tom matris.A $null array isn't the same thing as an empty array. Om du vet att du har en matris kontrollerar du antalet objekt i den.If you know you have an array, check the count of objects in it. Om matrisen är är $null antalet 0 .If the array is $null, the count is 0.

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

Det finns ytterligare en svällning att titta närmare på.There is one more trap to watch out for here. Du kan använda count även om du har ett enda objekt, om inte objektet är ett PSCustomObject .You can use the count even if you have a single object, unless that object is a PSCustomObject. Detta är ett fel som korrigeras i PowerShell 6,1.This is a bug that is fixed in PowerShell 6.1. Det är goda nyheter, men många människor är kvar på 5,1 och behöver titta på det.That's good news, but a lot of people are still on 5.1 and need to watch out for it.

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

Om du fortfarande använder PowerShell 5,1 kan du figursätta objektet i en matris innan du kontrollerar antalet för att få ett korrekt antal.If you're still on PowerShell 5.1, you can wrap the object in an array before checking the count to get an accurate count.

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

Kontrol lera och kontrol lera antalet för att kunna spela upp det säkert $null .To fully play it safe, check for $null, then check the count.

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

Alla-EQAll -eq

Jag såg nyligen någon fråga om att [kontrol lera att varje värde i en matris matchar ett angivet värde][].I recently saw someone ask how to verify that every value in an array matches a given value. Reddit User /u/BIS hade denna smarta- [lösning][] som söker efter felaktiga värden och vänder sedan resultatet.Reddit user /u/bis had this clever solution that checks for any incorrect values and then flips the result.

$results = Test-Something
if ( -not ( $results -ne 'Passed') )
{
    'All results a Passed'
}

Lägga till i matriserAdding to arrays

Nu börjar du med att undrar hur du lägger till objekt i en matris.At this point, you're starting to wonder how to add items to an array. Det snabba svaret är att du inte kan.The quick answer is that you can't. En matris är en fast storlek i minnet.An array is a fixed size in memory. Om du behöver utöka den eller lägga till ett enda objekt i det måste du skapa en ny matris och kopiera alla värden från den gamla matrisen.If you need to grow it or add a single item to it, then you need to create a new array and copy all the values over from the old array. Detta låter till exempel mycket arbete, men PowerShell döljer komplexiteten vid skapandet av den nya matrisen.This sounds like a lot of work, however, PowerShell hides the complexity of creating the new array. I PowerShell implementeras additionsoperatorn ( + ) för matriser.PowerShell implements the addition operator (+) for arrays.

Anteckning

PowerShell implementerar inte en subtraktion-åtgärd.PowerShell does not implement a subtraction operation. Om du vill ha ett flexibelt alternativ till en matris måste du använda ett generiskt List objekt.If you want a flexible alternative to an array, you need to use a generic List object.

Mat ris tilläggArray addition

Vi kan använda operatorn addition med arrayer för att skapa en ny matris.We can use the addition operator with arrays to create a new array. Vi har fått dessa två matriser:So given these two arrays:

$first = @(
    'Zero'
    'One'
)
$second = @(
    'Two'
    'Three'
)

Vi kan lägga till dem tillsammans för att få en ny matris.We can add them together to get a new array.

PS> $first + $second

Zero
One
Two
Three

Plus lika med + =Plus equals +=

Vi kan skapa en ny matris på plats och lägga till ett objekt i den så här:We can create a new array in place and add an item to it like this:

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

Kom bara ihåg att varje gång du använder += som du duplicerar och skapar en ny matris.Just remember that every time you use += that you're duplicating and creating a new array. Detta är inte ett problem för små data uppsättningar, men det skalas extremt dåligt.This is a not an issue for small datasets but it scales extremely poorly.

Pipeline-tilldelningPipeline assignment

Du kan tilldela resultatet av en pipeline till en variabel.You can assign the results of any pipeline into a variable. Det är en matris om den innehåller flera objekt.It's an array if it contains multiple items.

$array = 1..5 | ForEach-Object {
    "ATX-SQL-$PSItem"
}

Normalt när vi tänker på att använda pipelinen kommer vi att tänka på en typisk PowerShell-liners.Normally when we think of using the pipeline, we think of the typical PowerShell one-liners. Vi kan utnyttja pipelinen med foreach() instruktioner och andra slingor.We can leverage the pipeline with foreach() statements and other loops. I stället för att lägga till objekt i en matris i en slinga kan vi släppa objekt i pipelinen.So instead of adding items to an array in a loop, we can drop items onto the pipeline.

$array = foreach ( $node in (1..5))
{
    "ATX-SQL-$node"
}

Mat ris typerArray Types

Som standard skapas en matris i PowerShell som en [PSObject[]] typ.By default, an array in PowerShell is created as a [PSObject[]] type. Detta gör att den kan innehålla alla typer av objekt eller värden.This allows it to contain any type of object or value. Detta fungerar eftersom allt ärvs från PSObject typen.This works because everything is inherited from the PSObject type.

Starkt skrivna matriserStrongly typed arrays

Du kan skapa en matris av vilken typ som helst med hjälp av samma syntax.You can create an array of any type using a similar syntax. När du skapar en starkt angiven matris får den bara innehålla värden eller objekt av den angivna typen.When you create a strongly typed array, it can only contain values or objects the specified type.

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'

ArrayListArrayList

Att lägga till objekt i en matris är en av dess största begränsningar, men det finns några andra samlingar som vi kan göra för att lösa problemet.Adding items to an array is one of its biggest limitations, but there are a few other collections that we can turn to that solve this problem.

ArrayListÄr vanligt vis ett av de första saker som vi tänker på när vi behöver en matris som är snabbare att arbeta med.The ArrayList is commonly one of the first things that we think of when we need an array that is faster to work with. Den fungerar som en objekt mat ris varje plats som vi behöver det, men det hanterar snabbt tillägg av objekt.It acts like an object array every place that we need it, but it handles adding items quickly.

Så här skapar vi en ArrayList och lägger till objekt i den.Here is how we create an ArrayList and add items to it.

$myarray = [System.Collections.ArrayList]::new()
[void]$myArray.Add('Value')

Vi ringer till .NET för att få den här typen.We are calling into .NET to get this type. I det här fallet använder vi Standardkonstruktorn för att skapa den.In this case, we are using the default constructor to create it. Sedan anropar vi Add metoden för att lägga till ett objekt i det.Then we call the Add method to add an item to it.

Anledningen till att jag använder [void] i början av raden är att utelämna retur koden.The reason I'm using [void] at the beginning of the line is to suppress the return code. Vissa .NET-anrop gör detta och kan skapa oväntade utdata.Some .NET calls do this and can create unexpected output.

Om de enda data som du har i matrisen är strängar, tar du också en titt på att använda StringBuilder.If the only data that you have in your array is strings, then also take a look at using StringBuilder. Det är nästan samma sak men har några metoder som bara är för att hantera strängar.It's almost the same thing but has some methods that are just for dealing with strings. StringBuilderÄr särskilt utformad för prestanda.The StringBuilder is specially designed for performance.

Det är vanligt att du ser att personer flyttas till ArrayList från matriser.It's common to see people move to ArrayList from arrays. Men det kommer från en tid där C# inte hade generisk support.But it comes from a time where C# didn't have generic support. ArrayListÄr föråldrad i stöd för den generiskaList[]The ArrayList is deprecated in support for the generic List[]

Allmän listaGeneric List

En generisk typ är en särskild typ i C# som definierar en generaliserad klass och användaren anger de data typer som används när den skapas.A generic type is a special type in C# that defines a generalized class and the user specifies the data types it uses when created. Så om du vill ha en lista med tal eller strängar definierar du att du vill ha en lista över int eller string typer.So if you want a list of numbers or strings, you would define that you want list of int or string types.

Så här skapar du en lista med strängar.Here is how you create a List for strings.

$mylist = [System.Collections.Generic.List[string]]::new()

Eller en lista med tal.Or a list for numbers.

$mylist = [System.Collections.Generic.List[int]]::new()

Vi kan omvandla en befintlig matris till en lista som detta utan att först skapa objektet:We can cast an existing array to a list like this without creating the object first:

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

Vi kan förkorta syntaxen med using namespace instruktionen i PowerShell 5 och senare.We can shorten the syntax with the using namespace statement in PowerShell 5 and newer. usingInstruktionen måste vara den första raden i skriptet.The using statement needs to be the first line of your script. Genom att deklarera ett namn område kan du använda PowerShell för att lämna det av data typerna när du refererar till dem.By declaring a namespace, PowerShell lets you leave it off of the data types when you reference them.

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

Detta gör det List mycket mer användbart.This makes the List much more usable.

Du har en liknande Add metod som är tillgänglig för dig.You have a similar Add method available to you. Till skillnad från ArrayList finns det inget retur värde för metoden, Add så vi behöver inte göra void det.Unlike the ArrayList, there is no return value on the Add method so we don't have to void it.

$myList.Add(10)

Och vi har fortfarande åtkomst till elementen som andra matriser.And we can still access the elements like other arrays.

PS> $myList[-1]
10

Lista [PSObject]List[PSObject]

Du kan ha en lista över vilken typ som helst, men när du inte vet vilken typ av objekt du kan använda [List[PSObject]] för att ta med dem.You can have a list of any type, but when you don't know the type of objects, you can use [List[PSObject]] to contain them.

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

Remove()Remove()

ArrayListOch generiskt List[] stöder borttagning av objekt från samlingen.The ArrayList and the generic List[] both support removing items from the collection.

using namespace System.Collections.Generic
$myList = [List[string]]@('Zero','One','Two','Three')
[void]$myList.Remove("Two")
Zero
One
Three

När du arbetar med värde typer tar den bort det första från listan.When working with value types, it removes the first one from the list. Du kan anropa det igen om du vill fortsätta att ta bort värdet.You can call it over and over again to keep removing that value. Om du har referens typer måste du ange det objekt som du vill ta bort.If you have reference types, you have to provide the object that you want removed.

[list[System.Management.Automation.PSDriveInfo]]$drives = Get-PSDrive
$drives.remove($drives[2])
$delete = $drives[2]
$drives.remove($delete)

Metoden Remove returnerar true om den kunde hitta och ta bort objektet från samlingen.The remove method returns true if it was able to find and remove the item from the collection.

Fler samlingarMore collections

Det finns många andra samlingar som kan användas, men de är bra generiska matriser.There are many other collections that can be used but these are the good generic array replacements. Om du är intresse rad av att lära dig mer av de här alternativen kan du ta en titt på det här registret som markerar Kraus .If you're interested in learning about more of these options, take a look at this Gist that Mark Kraus put together.

Andra olika delarnaOther nuances

Nu när jag har täckt alla större funktioner finns här några saker som jag ville nämna innan jag omsluter detta.Now that I have covered all the major functionality, here are a few more things that I wanted to mention before I wrap this up.

I storleks mat risPre-sized arrays

Jag nämnde att du inte kan ändra storleken på en matris när den har skapats.I mentioned that you can't change the size of an array once it's created. Vi kan skapa en matris med en fördefinierad storlek genom att anropa den med new($size) konstruktorn.We can create an array of a pre-determined size by calling it with the new($size) constructor.

$data = [Object[]]::new(4)
$data.count
4

Multiplicerar matriserMultiplying arrays

Ett intressant litet stick är att du kan multiplicera en matris med ett heltal.An interesting little trick is that you can multiply an array by an integer.

PS> $data = @('red','green','blue')
PS> $data * 3
red
green
blue
red
green
blue
red
green
blue

Initiera med 0Initialize with 0

Ett vanligt scenario är att du vill skapa en matris med enbart nollor.A common scenario is that you want to create an array with all zeros. Om du bara kommer att använda heltal, är en stark inskriven matris med heltal som standard alla nollor.If you're only going to have integers, a strongly typed array of integers defaults to all zeros.

PS> [int[]]::new(4)
0
0
0
0

Vi kan även använda det multipliceringa sticket för att göra detta.We can use the multiplying trick to do this too.

PS> $data = @(0) * 4
PS> $data
0
0
0
0

Det som är trevligt om att multiplicera sticket är att du kan använda vilket värde som helst.The nice thing about the multiplying trick is that you can use any value. Så om du hellre vill ha det 255 som standardvärde, är det ett bra sätt att göra det.So if you would rather have 255 as your default value, this would be a good way to do it.

PS> $data = @(255) * 4
PS> $data
255
255
255
255

Kapslade matriserNested arrays

En matris i en matris kallas för en kapslad matris.An array inside an array is called a nested array. Jag använder inte dessa mycket i PowerShell men jag har använt dem på andra språk.I don't use these much in PowerShell but I have used them more in other languages. Överväg att använda en matris med matriser när dina data passar i ett rutnät som mönster.Consider using an array of arrays when your data fits in a grid like pattern.

Här följer två sätt att skapa en tvådimensionell matris.Here are two ways we can create a two-dimensional array.

$data = @(@(1,2,3),@(4,5,6),@(7,8,9))

$data2 = @(
    @(1,2,3),
    @(4,5,6),
    @(7,8,9)
)

Kommatecknet är mycket viktigt i de här exemplen.The comma is very important in those examples. Jag fick ett tidigare exempel på en normal matris på flera rader där kommatecknet var valfritt.I gave an earlier example of a normal array on multiple lines where the comma was optional. Det är inte fallet med en flerdimensionell matris.That isn't the case with a multi-dimensional array.

Hur vi använder index notation ändras en aning nu när vi har en kapslad matris.The way we use the index notation changes slightly now that we've a nested array. Vi använder $data ovanstående för att få åtkomst till värdet 3.Using the $data above, this is how we would access the value 3.

PS> $outside = 0
PS> $inside = 2
PS> $data[$outside][$inside]
3

Lägg till en uppsättning hakparenteser för varje nivå av mat ris kapsling.Add a set of bracket for each level of array nesting. Den första uppsättningen hakparenteser är för den yttre mest matrisen och sedan arbetar du på ditt sätt i därifrån.The first set of brackets is for the outer most array and then you work your way in from there.

Write-Output-noenumerationWrite-Output -NoEnumerate

PowerShell gillar att packa upp eller räkna upp matriser.PowerShell likes to unwrap or enumerate arrays. Detta är en grund aspekt av hur PowerShell använder pipelinen, men det finns tillfällen då du inte vill att det ska hända.This is a core aspect of the way PowerShell uses the pipeline but there are times that you don't want that to happen.

Jag rör ofta objekt till Get-Member för att lära sig mer om dem.I commonly pipe objects to Get-Member to learn more about them. När jag rör en matris till den, kommer den att bli figursatt och Get-Member ser medlemmarna i matrisen och inte själva matrisen.When I pipe an array to it, it gets unwrapped and Get-Member sees the members of the array and not the actual array.

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

Du kan använda för att förhindra att matrisen bryts av Write-Object -NoEnumerate .To prevent that unwrap of the array, you can use Write-Object -NoEnumerate.

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

Jag har ett andra sätt som är mer av ett Hack (och jag försöker undvika hackningar som detta).I have a second way that's more of a hack (and I try to avoid hacks like this). Du kan placera ett kommatecken framför matrisen innan du rör det.You can place a comma in front of the array before you pipe it.

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

Returnera en matrisReturn an array

Den här omplaceringen av matriser sker också när du matar ut eller returnerar värden från en funktion.This unwrapping of arrays also happens when you output or return values from a function. Du kan fortfarande hämta en matris om du tilldelar utdata till en variabel, så det är inte ofta ett problem.You can still get an array if you assign the output to a variable so this isn't commonly an issue.

Fångsten är att du har en ny matris.The catch is that you have a new array. Om det skulle uppstå ett problem kan du använda Write-Output -NoEnumerate $array eller return ,$array för att undvika det.If that is ever a problem, you can use Write-Output -NoEnumerate $array or return ,$array to work around it.

Något mer?Anything else?

Jag vet att det är allt du behöver göra i.I know this is all a lot to take in. Min idé är att du lär dig något från den här artikeln varje gång du läser det och att det blir en lämplig referens till dig under lång tid att komma.My hope is that you learn something from this article every time you read it and that it turns out to be a good reference for you for a long time to come. Om du har hittat detta för att vara till hjälp kan du dela den med andra som du tror kan få ett värde av det.If you found this to be helpful, please share it with others you think may get value out of it.

Härifrån rekommenderar vi att du tar en titt på ett liknande inlägg som jag skrev om hash.From here, I would recommend you check out a similar post that I wrote about hashtables.