Working With The Collection Extension Methods (2 of 3)
February 6, 2017
powershell collections .net itsajoke butnotreallyPredicates
Okay. So, we have this collection.
posh> $list
Mike
Bob
Wendy
Michele
Which has a method called FindAll that takes a Predicate.
posh> $list.FindAll
OverloadDefinitions
-------------------
System.Collections.Generic.List[string] FindAll(System.Predicate[string] match)
What is a predicate? WikiPedia simply puts it like this.
A predicate is a statement that may be true or false depending on the values of its variables
If you’ve written some SQL in your life, a Where
clause is a predicate.
It is the test of values you want to return.
You probably do this all of the time in PowerShell as well.
Get-ChildItem | Where-Object {$_.Length -gt 1000}
So, if the ScriptBlock of a Where-Object command is a predicate will that work for FindAll?
Almost.
Since we are not in a pipeline, we don’t have the automatic $_
variable.
You can tell by the method definition, System.Predicate[string]
that the method will operate on a string.
Basically, we need to give the method a way to bind the values in the collection to a variable in the predicate ScriptBlock.
This is simple enough to do with a param
block.
Our complete Predicate object ends up looking like this.
posh> $list.FindAll({param($s) $s.length -ge 7})
Michele
Another useful method of the Generic.List is TrueForAll()
.
It has the same method parameter.
posh> $list.TrueForAll({ param([string]$s) $s.Length -lt 8})
True
posh> $list.TrueForAll({ param([string]$s) $s.Length -lt 7})
False
We are only getting started
In part 1, we listed a bunch of methods available for Generic.List. That is actually not all of the methods available. Generic.List implements IEnumerable which provides a long list of additional methods for querying and manipulating collections.
I think most of these are extension methods. Extension methods add additional methods to another type. Unfortunately, PowerShell does not wire up extension methods and you have to work with them as static methods. So, let’s examine one of those methods, Zip. This isn’t a method to create a .Zip file archive, but a method that, “Applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.” In layman’s terms, takes two collections in and spits a single collection out based on a function you provide.
posh> [System.Linq.Enumerable]::Zip
OverloadDefinitions
-------------------
static System.Collections.Generic.IEnumerable[TResult] Zip[TFirst, TSecond,
TResult](System.Collections.Generic.IEnumerable[TFirst] first, System.Collections.Generic.IEnumerable[TSecond] second,
System.Func[TFirst,TSecond,TResult] resultSelector)
There is a lot there, but the part I want to draw you attention to is System.Func[TFirst,TSecond,TResult] resultSelector
.
This is the parameter where you supply your function to combine the two collections.
You’ll notice it is not a Predicate type, but a Func.
This concludes our broadcast day
In part 3, we’ll break down what this definition is asking for and how to build one in PowerShell.