Given a list of items in PowerShell, how do I find the index of the current item from within a loop?
For example:
$letters = { 'A', 'B', 'C' }
$letters | % {
# Can I easily get the index of $_ here?
}
The goal of all of this is that I want to output a collection using Format-Table and add an initial column with the index of the current item. This way people can interactively choose an item to select.
.NET has some handy utility methods for this sort of thing in System.Array:
PS> $a = 'a','b','c'
PS> [array]::IndexOf($a, 'b')
1
PS> [array]::IndexOf($a, 'c')
2
Good points on the above approach in the comments. Besides "just" finding an index of an item in an array, given the context of the problem, this is probably more suitable:
$letters = { 'A', 'B', 'C' }
$letters | % {$i=0} {"Value:$_ Index:$i"; $i++}
Foreach (%) can have a Begin sciptblock that executes once. We set an index variable there and then we can reference it in the process scripblock where it gets incremented before exiting the scriptblock.
I am not sure it's possible with an "automatic" variable. You can always declare one for yourself and increment it:
$letters = { 'A', 'B', 'C' }
$letters | % {$counter = 0}{...;$counter++}
Or use a for
loop instead...
for ($counter=0; $counter -lt $letters.Length; $counter++){...}
> "A,B,C,D,E,F,G" -split "," | % { $i = 0 } { if ( $i -gt 3 ) { $_ }; ++$i }
Output: E F G
dir | % {$i = 46}{ move-item $_ ("ARM-{0:00000}.pdf" -f $i++)}
$letters | % {$counter...
option is safe even if $letters
is only one object and not an array where as the for
option doesn't handle that properly.
$selected = $true,$false,$true; @('first','second','third') | % {$i=0}{If($selected[$i]){$_};$i++ }
to return 'first' and 'third'
For PowerShell 3.0 and later, there is one built in :)
foreach ($item in $array) {
$array.IndexOf($item)
}
0..($letters.count-1) | foreach { "Value: {0}, Index: {1}" -f $letters[$_],$_}
For those coming here from Google like I did, later versions of Powershell have a $foreach
automatic variable. You can find the "current" object with $foreach.Current
$_
for the current object. Also, OP's question was about finding the index of the current object, not the object itself.
Success story sharing
IndexOf
works if your sure you always have an array but the$letters | % {$i=0}...
method is safe even if$letters
ends up being only one object and not an array.