3

Is there a more elegant way to write the following if statement in PowerShell

[ValidateNotNull()]
[ValidateSet('Service', 'Role', 'RoleService', 'Feature', 'Group', 'File', 'Package')]
[Parameter(Mandatory = $true, Position = 1)]
[string[]]
$ProcessingModes

if ($ProcessingModes -contains 'Role' -or $ProcessingModes -contains 'RoleService' -or $ProcessingModes -contains 'Feature')
{
}
1
  • can $ProcessingModes contain multiple values (e.g. array) or just a single value? Commented Apr 29, 2014 at 21:45

4 Answers 4

5

You can do array intersection quite easily with this:

$keyModes = 'Role', 'RoleService', 'Feature'
if ($keyModes | ? { $ProcessingModes -contains $_ }) { "found at least one" }
Sign up to request clarification or add additional context in comments.

Comments

2

Your question is basically, is there an operator in PowerShell which determines whether the intersection between two arrays is non-empty. The answer is no, there is not. Additionally, after reviewing the question Powershell, kind of set intersection built-in?, it looks like the best approach is to use HashSet objects instead of arrays, which do expose IntersectWith and UnionWith methods.

Comments

2

You could use a RegEx instead. Here's how I would do it:

$ProcessingModes = @('Role','Service')
if ($ProcessingModes -match '\b(Role|RoleService|Feature)\b') {
    'it matches'
} else {
    'it does not match'
}
it matches

$ProcessingModes = @('RoleGroup','Service')
if ($ProcessingModes -match '\b(Role|RoleService|Feature)\b') {
    'it matches'
} else {
    'it does not match'
}
it does not match

The \b is a word boundary. It's equivalent to search "as whole word". It's not absolutely necessary in your code because of your ValidateSet, but it would provide useful to avoid finding "Role" in another word like "RoleGroup" if you ever permit it. You could try removing both \b in the second example to see it matches.

I think this will make your code more readable and probably more elegant.

Comments

1

Since at least Powershell 5.1 you can use Compare-Object for comparing two arrays of values. A simplified example

$ProcessingModes = 'Service', 'Role', 'RoleService', 'Feature', 'Group', 'File', 'Package'
$ModesToCompare = 'Role', 'RoleService', 'Feature'

$Comparison = Compare-Object -ReferenceObject $ProcessingModes -DifferenceObject $ModesToCompare -IncludeEquals

$Comparison will give you the following output:

InputObject SideIndicator
----------- -------------
Role        ==
RoleService ==
Feature     ==
Service     <=
Group       <=
File        <=
Package     <=

This means that Service, Group, File, and Package only existed in the -ReferenceObject. By adding the -IncludeEquals you get exactly what you're looking for. You can now take this output and check if SideIndicator contains ==, like so:

if($Comparison.SideIndicator -contains "=="}
    #some code here
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.