dcaz
dcaz

Reputation: 909

Array Row index function

I created a function to find an item in an array so I can update it.

  function Get-ArrayRowIndex {
                param(
                    [parameter(mandatory = $true)][array]$Property,
                    [parameter(mandatory = $true)][string]$Value
                )
           
                #Loop through array,incrementing index until value is found. Jordan wrote this and I refined it.
                [int]$index = 0
                while ($index -lt ($Property.count)) {
                    if ($Property[$index] -eq $Value) {
                        break
                    }
                    $index++
                }
                return [int]$index
            }

The problem is when the object is not found the function returns the total number of items in the array. How can I return an error if not found?

Upvotes: 2

Views: 1065

Answers (3)

Santiago Squarzon
Santiago Squarzon

Reputation: 60060

Normally a for loop is a cleaner approach for this:

function Get-ArrayRowIndex {
    param(
        [Parameter(Mandatory)]
        [array] $Property,

        [Parameter(Mandatory)]
        [string] $Value
    )

    for ($i = 0; $i -lt $Property.Count; $i++) {
        if ($Property[$i] -eq $Value) {
            return $i
        }
    }

    throw "$Value not found in this array."
}

$arr = 0..10
Get-ArrayRowIndex $arr 4  # => returns 4
Get-ArrayRowIndex $arr 11 # => throws "11 not found in this array."

Upvotes: 3

iRon
iRon

Reputation: 23663

The PowerShell way, using Select-String:

$Properties = 'One', 'Two', 'Three'
$Value = 'Two'
($Properties | Select-String -SimpleMatch -Pattern $Value).LineNumber

2

Throwing errors:

$Found = $Properties | Select-String -SimpleMatch -Pattern $Value
Switch ($Found.Count) {
    0       { Throw "$Value not found" }
    1       { $Found.LineNumber }
    Default { Throw "More than one $Value found" }
}

Upvotes: 3

mklement0
mklement0

Reputation: 438018

If you want to throw an error in case the value isn't found:

function Get-ArrayRowIndex {
                param(
                    [parameter(mandatory = $true)][array]$Property,
                    [parameter(mandatory = $true)][string]$Value
                )
           
                [int]$index = 0
                while ($index -lt ($Property.count)) {
                    if ($Property[$index] -eq $Value) {
                        # Found -> output the value and return (exit) here.
                        return $index 
                    }
                    $index++
                }
                # Getting here means that the value wasn't found.
                throw "'$Value' not found in the given array."
            }

Note that you could use the [Array]::FindIndex() method instead of looping through the array yourself:

# Returns the index if found; -1 otherwise.
[Array]::FindIndex(
  $Property, 
  [Predicate[object]] { $Value -eq $args[0] }
)

[Array].IndexOf() is another option, but only if case-sensitive string comparison is desired (whereas PowerShell's operators, such as -eq used above, are case-insensitive by default); e.g., ('FOO', 'bar').IndexOf('foo') yields -1 (not found) and ('FOO', 'foo').IndexOf('foo') yields 1

Upvotes: 4

Related Questions