In a recent StackOverflow answer, I wrote the following PowerShell to find parameters that were in a given parameter set (edited somewhat for purposes of this post):
$commandName='Get-ChildItem' $ParameterSetToMatch='LiteralItems' $ParameterList = (Get-Command -Name $commandName).Parameters.Values foreach($parameter in $parameterList){ $parameterSets=$parameter.ParameterSets.Keys if ($parameterSets -contains $parameterSetToMatch ){ write-output $parameter.Name } }
A quick note…it’s not correct. It only shows parameters that are explicitly in the parameter set. Items that aren’t marked with any parameter set are in all parameter sets, and this doesn’t include them. That is beside the point.
Note that I’m looking through collections with a loop and an if statement.
A bit better
I could have made it a bit better with Where-Object (it’s still a bit bad because hashtable iteration isn’t nice):
$ParameterList.GetEnumerator() | Where-Object {$_.Value.parameterSets.Keys -contains 'Items'} | Select-Object -Property Key
The “new” way
When I say new, I mean “PowerShell 3.0 new”. I still have a lot of PowerShell 1.0 muscle-memory that I need to get rid of. This post is part of the attempt. 🙂
Now, I’m going to use two features that were added to PowerShell 3.0 that I don’t use often enough: Member Enumeration and Where().
Member Enumeration says I can refer to members of the items in the collection through the collection.
For instance,
(Get-ChildItem -file).Length
Get-ChildItem returned a collection of files which each have a length property.
So instead of using ForEach-Object or Select-Object, I can use dot-notation against the collection and get the properties of the items in the collection. Nifty shortcut.
The second feature I’m going to use is the Where() method. This method is available with any collection object, and is (in the simplest case) just like using Where-Object.
Putting those two together, I get this:
$ParameterList.GetEnumerator().Where{$_.Value.parameterSets.Keys -contains 'Items'}.Key
What is amazing about this to me isn’t how short it is (although it is short).
The amazing part is that I logically looped through a collection of objects looking for items in the collection which matched specific criteria, then extracted a particular property of those objects….and I didn’t need to use a pipeline at all.
I’m a big fan of pipelines, and the general-purpose *-Object cmdlets allow us to manipulate data with ease. However, that power comes at a price. Pipelines cost memory and time. This expression doesn’t incur the “penalties” of using a pipeline but gets us all of the benefit.
What do you think? Is the new version better?
Pingback: Old School PowerShell Expressions vs New - PowerShell Station - How to Code .NET
Pingback: Dew Drop - June 26, 2018 (#2753) - Morning Dew