Reputation: 6883
I have a string I am pulling from XML that SHOULD contain comma separated integer values. Currently I am using this to convert the string to an array and test each member of the array to see if it is an Int. Ultimately I still want an array in the end, as I also have an array of default success codes and I want to combine them. That said, I have never found this pattern of setting the test condition true then looping and potentially setting it to false to be all that elegant. So, I am wondering if there is a better approach. I mean, this works, and it's fast, and the code is easy to read, so in a sense there is no reason to change it, but if there is a better way...
$supplamentalSuccessCode = ($string.Split(',')).Trim()
$validSupplamentalSuccessCode = $true
foreach ($code in $supplamentalSuccessCode) {
if ($code -as [int] -isNot [int]) {
$validSupplamentalSuccessCode = $false
}
}
EDIT: To clarify, this example is fairly specific, but I am curious about a more generic solution. So imagine the array could contain values that need to be checked against a lookup table, or local drive paths that need to be checked with Test-Path. So more generically, I wonder if there is a better solution than the Set variable true, foreach, if test fails set variable false logic. Also, I have played with a While loop, but in most situations I want to find ALL bad values, not exit validation on the first bad one, so I can provide the user with a complete error in a log. Thus the ForEach loop approach I have been using.
Upvotes: 1
Views: 1053
Reputation: 440657
In PSv4+ you can enlist the help of the .Where()
collection "operator" to determine all invalid values:
Here's a simplified example:
# Sample input.
$string = '10, no, 20, stillno, -1'
# Split the list into an array.
$codes = ($string.Split(',')).Trim()
# Test all array members with a script block passed to. Where()
# As usual, $_ refers to the element at hand.
# You can perform whatever validation is necessary inside the block.
$invalidCodes = $codes.Where({ $null -eq ($_ -as [int]) })
$invalidCodes # output the invalid codes, if any
The above yields:
no
stillno
Note that what .Where()
returns is not a regular PowerShell array ([object[]]
), but an instance of [System.Collections.ObjectModel.Collection[PSObject]]
, but in most situations the difference shouldn't matter.
A PSv2-compatible solution is a bit more cumbersome:
# Sample input.
$string = '10, no, 20, stillno, -1'
# Split the list into an array.
# Note: In PSv*3* you could use the simpler $codes = ($string.Split(',')).Trim()
# as in the PSv4+ solution.
$codes = foreach ($code in $string.Split(',')) { $code.Trim() }
# Emulate the behavior of .Where() with a foreach loop:
# Note that do you get an [object[]] instance back this time.
$invalidCodes = foreach ($code in $codes) { if ($null -eq ($code -as [int])) { $code } }
Upvotes: 1