Passing each element of an array into a function with Powershell

Let's say you have a collection of objects, and you wish to perform the same action over each object in that collection.

Seems like a ForEach job, right? Let's use this as an starting point:

$myArray = @('Here', 'are', 'some', 'things')

$myArray | ForEach-Object `
    -Begin { $i = 0 } `
    -Process { $i++ } `
    -End { Write-Host $i }

In this example, we go through each object, increment i, and finally output the value of $i to the console.

4

Not particularly helpful, but it is going over each element at least. In a real-world scenario however, we probably want to do something with each value in the collection.

We can grab the value of the object using $_ :

$myArray = @('Here', 'are', 'some', 'things')

$myArray | ForEach-Object `
	-Begin { Write-Host "Start!" } `
	-Process { Write-Host $_ } `	-End {Write-Host "Finished!"}
Start!
Here
are
some
things
Finished!

Rewriting as a function

What if we wanted to do something a bit more involved than writing everything out to the screen?

We could create a function, and run it inside the Process section, passing in the parameter. Or, we could create a function that iterates through the collection itself.

Let's consider the above example, writing it as a function:

$myArray = @('Here', 'are', 'some', 'things')

function DoStuff 
{
    Begin { Write-Host "Start!" } 
    Process { Write-Host $_ } 
    End { Write-Host "Finished!" }
}

# Run DoStuff on every element in myArray
$myArray | DoStuff

Here, we've taken the -Begin, -Process and -End arguments, and placed them inside the function. This allows us to pipe the $myArray variable simply with the function name:

$myArray | DoStuff
Start!
Here
are
some
things
Finished!

Of course, in this example we didn't even need the Begin and End steps. These can be omitted:

$myArray = @('Here', 'are', 'some', 'things')

function DoStuff 
{
    Process {
		# Assume this is a long, complex method
		Write-Host $_ 
	} 
}

$myArray | DoStuff
Here
are
some
things

Writing functions like this makes it much easier to iterate over them, whilst keeping the code readable.

Iterating over objects

In these examples, the object is simply a string.

If the object has properties, then we can get the property from $_:

function DoStuff 
{
	# Get the Name from the object only    Process { Write-Host $_.Name } }

$objectA = [PSCustomObject]@{ Name = 'Here' }
$objectB = [PSCustomObject]@{ Name = 'are' }
$objectC = [PSCustomObject]@{ Name = 'some' }
$objectD = [PSCustomObject]@{ Name = 'things' }
$myArray = @($objectA, $objectB, $objectC, $objectD)

$myArray | DoStuff