Search notes:

PowerShell: Arrays

Simple array related expressions

Arrays can be created with a comma (,) and subscripted with a bracket. Negative indices refer to the elements in the array counting from the end.
The number of elements in an array can be found via .count or .length.
The elements in an array can be iterated over with the cmdlet foreach-object or the foreach statement. (An example of this technique is outlined in apply a transformation on each element of an array).
$ary = 'foo', 'bar', 'baz'

write-output "First element is:  $($ary[0])"
write-output "Second element is: $($ary[1])"
write-output "Last element is:   $($ary[-1])"
write-output "The array has $($ary.count) elements"
#
# First element is:  foo
# Second element is: bar
# Last element is:   baz
# The array has 3 elements

# Iterating over the array using the foreach-object cmdlet …
$ary | foreach-object { $_.ToUpper() }

# … or the foreach statement: 
foreach ($elem in $ary) {
   $elem.ToUpper() 
}
Github repository about-PowerShell, path: /language/type/array/intro.ps1

Printing arrays

By default, the elements are printed one below an another when printing an array. In order to print all elements on one line, the -join operator can be used:
$days = 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
write-output $days
#
# Sun
# Mon
# Tue
# Wed
# Thu
# Fri
# Sat

write-output($days -join ' ')
#
# Sun Mon Tue Wed Thu Fri Sat
Github repository about-PowerShell, path: /language/type/array/print.ps1

Creating arrays with the comma operator vs. the plus operator

An array can be created with the comma operator ($ary = $foo, $bar, $baz). If one of the elements from which the array is created (for example $bar) is itself an array, the element is not unpacked (or exploded) so that the resulting array in this example always has three elements.
Sometimes, however, it is desired to unpack the elements of an array when a new array is created. This is possible by using the plus operator rather than the comma operator.
The following example tries to demonstrate exactly this:
$abc = 'a', 'b', 'c'
$abc.length
#
# 3

# ----- Create an array with the comma operator
#
#       $abc is turned into one element so that
#       the resulting array consists of 4 elements:

$ary = $abc, 'd', 'e', 'f'
$ary.length
#
# 4

$ary | foreach-object { "$_" }
#
# a b c
# d
# e
# f

# ----- Create an array with the plus operator
#
#       The elements in $abc are exploded/expanded
#       so that the resulting array consists
#       of 6 elements:

$ary = $abc + 'd', 'e', 'f'
$ary.length
#
# 6

$ary | foreach-object { "$_" }
#
# a
# b
# c
# d
# e
# f
Github repository about-PowerShell, path: /language/type/array/plus-vs-comma.ps1

Creating an array with zero or one element

An empty array or an array with one element can be created with the array subexpression operator @( … ).
PS C:\> $ary = @()
PS C:\> $bry = @(42)
An array with one element can alternatively also be created with a leading comma. In this case, the comma is a unary operator that explicitly creates a one-element array:
PS C:\> $one = ,1
PS C:\> $one -is [array]
True
PS C:\> $one.length
1
Compare with @{ … } which creates hash tables.

Creating an array with a predefined number of elements

[string[]] $metaVars = new-object string[] 3
$metaVars.length
$metaVars[0] = 'foo' ; $metaVars[1] = 'bar' ; $metaVars[2] = 'baz'

$metaVars[3] = 'booom!' # --> Index was outside the bounds of the array.

Adding elements to an array

The += operator allows to add elements to an array:
PS:\> $ary += 'one'
PS:\> $ary += 'two'
PS:\> $ary += 'three'

Filtering and removing elements

Elements can be filtered with some comparison operators.
The following example returns the elements that are (alphabetically) greater than ghikj:
$elems = 'one', 'two', 'three', 'four', 'five', 'six'
$elems -gt 'ghijk' -join ', '
#
# one, two, three, six
Github repository about-PowerShell, path: /language/type/array/filter.ps1
Elements can be removed from an array by using the more explicit where-object cmdlet and (for example) the -notmatch operator:
PS:\> $ary = $ary | where-object { $_ -notmatch 'two' }

Weakly and strongly typed arrays

PowerShell (or .NET?) distinguishes between weakly typed and strongly typed arrays:
           $weakly___typed = 'ONE', 'TWO', 'THREE'
[string[]] $strongly_typed = 'one', 'two', 'three'

write-output "An weakly   typed array is $($weakly___typed.GetType().FullName) and derives from $($weakly___typed.GetType().BaseType.FullName)"
write-output "An strongly typed array is $($strongly_typed.GetType().FullName) and derives from $($strongly_typed.GetType().BaseType.FullName)"
#
# An weakly   typed array is System.Object[] and derives from System.Array
# An strongly typed array is System.String[] and derives from System.Array
Github repository about-PowerShell, path: /language/type/array/weakly-and-strongly-typed.ps1

An array can contain different data types

A weakly typed array can contain different data types.
PS:\> $ary = 42, 'foo', (get-date)

Sorting arrays

A non-numeric array can be sorted numerically like so:
$ary          =    '9', '10', '1', '888'
$ary | sort-object
#
# 1
# 10
# 888
# 9

$ary | sort-object { [int] $_ }
#
# 1
# 9
# 10
# 888
Github repository about-PowerShell, path: /language/type/array/numerically-sort-array.ps1

Nested arrays

Arrays can be nested.
In the following example, $ary has four elements, the third of which is an array that has three elements:
PS C:\> $ary = 0, 1, ('zero', 'one', 'two'), 3
PS C:\> $ary[2][1]
one

Functional programming

An array has a forEach method that is used like or at least similar to map as known in functional programming.
$ary.forEach(scriptblock expression)
$ary.forEach(type convertToType)
$ary.forEach(string propertyName)
$ary.forEach(string propertyName, object[] newValue)
$ary.forEach(string methodName)
$ary.forEach(string methodName, object[] arguments)
$ary.forEach(scriptblock expression, object[] arguments)
Apparently, there are now spaces allowed between the forEach operator and the following opening parenthesis.
There is also a where method that is similar to a functional programming's filter function
$ary.where(scriptblock expression[, WhereOperatorSelectionMode mode [, int numberToReturn]])

Unrolling an array

The values all elements' properties with a given name can be accessed with what is called unrolling:
$ary = [psCustomObject] @{ propA = 'one'  ; propB = 'foo' },
       [psCustomObject] @{ propA = 'two'  ; propB = 'bar' },
       [psCustomObject] @{ propA = 'three'; propB = 'baz' }

echo ($ary.propA -join ' - ')
#
#  one - two - three

echo ($ary.propB -join ' - ')
#
#  foo - bar - baz
Github repository about-PowerShell, path: /language/type/array/unrolling.ps1

Cmdlets/functions returning arrays

Returning arrays with an indeterminate number of eleements

Some cmdlets return arrays with an indeterminate number of elements (usually all of the same type):
PS C:\> $services = get-service
PS C:\> $services[0].name
AeLookupSvc
PS C:\> $services[1].name
ALG
PS C:\> $services[-1].name
ZeroConfigService
In a pipeline, the elements of the returned array can be sent to a forEach-object cmdlet to process each element of the array individually in a script block.
Within the script block, the automatic variable $_ (= $psItem) refers to the item being processed:
function doSomethingWithService {
  …
}
get-service | forEach-object { doSomethingWithService $_ }

Returning a fixed number of elements

The following function returns an array with two elements with differing types. When invoked, the returned elements get assigned to two corresponding variables:
function two-objects() {
   return (get-random), (get-date)
}
 
$rand, $now = two-objects
write-host "Random number is $rand"
write-host "Date now is      $now"

The influence of $OFS

The preference variable $OFS influences how arrays are printed:
#
#  Create an array:
#
$ary = 'foo', 'bar', 'baz'

#
#  Initially, the variable OFS has not been assigned a value:
#
$OFS -eq $null
#
#  True

#
#  Printing the array in a string
#
write-output "$ary"
#
#  foo bar baz

#
#  Assign an empty string to OFS and
#  print the array again:
#
$OFS = ''
write-output "$ary"
#
#  foobarbaz

#
#  Assign a string to OFS and
#  print the array again:
#
$OFS = ' -+- '
write-output "$ary"
#
#  foo -+- bar -+- baz
Github repository about-PowerShell, path: /language/type/array/OFS.ps1

Assigning an array to an array

Quite similarly (but less powerfully) to Python's iterable unpacking, an array with n elements can be assigned to a an array with m (m <= n) elements so that the (n-m+1) elements of the array being assigned become the elements in the right-most element of the array being assigned to:
#
#  Define an array with five elements…
#
$numbers = 'one', 'two', 'three', 'four', 'five'

#
# … and assign it to an array with three elements:
#
$eins, $zwei, $rest = $numbers

#
#  $rest will have remaining elements of $numbers:
#
"eins = $eins"
"zwei = $zwei"
"rest = $rest"
Github repository about-PowerShell, path: /language/type/array/assign.ps1
This code prints
eins = one
zwei = two
rest = three four five
This technique can be used, for example, to iterate over an array that contains name-value pairs.
See also shifting function parameters and Perl's shift function.

Calling functions, passing arguments separated with commas

PowerShell separates arguments by whitespace, not by comma, When calling a function or cmdLet. Thus, the individual arguments (or parameters) must not be separated with commas because the commas construct an array.
The following example passes one argument, namely an array of three elements, to the function/cmdlet:
some-func 'foo', 'bar', 'baz'
Note: this is not the case when calling a .NET method. The following invocation passes two parameters, the strings 'PATH' and 'user', although these are separated by a comma:
[system.Environment].GetEnvironmentVariable('PATH', 'user')

See also

Some investigations on passing arrays as arguments to executables and PowerShells scripts.
A PowerShell script can be made more robust by making sure referenced object-members actually exist by using the statement set-strictMode -version 3 in a script.
foreach
The -contains operator can be used to check if a given value exists in an array.
Datatypes in PowerShell such as the byte array.
It is possible to create an array of string with the -split operator:
'foo:bar:baz' -split ':'
Converting a string to a char array

Index