获取PowerShell循环中当前项的索引

获取PowerShell循环中当前项的索引,powershell,Powershell,给定PowerShell中的项目列表,如何从循环中查找当前项目的索引 例如: $letters = { 'A', 'B', 'C' } $letters | % { # Can I easily get the index of $_ here? } 所有这些的目标是,我希望使用输出一个集合,并使用当前项的索引添加一个初始列。通过这种方式,人们可以交互选择要选择的项目。我不确定使用“自动”变量是否可行。您始终可以为自己声明一个并递增它: $letters = { 'A', 'B', 'C

给定PowerShell中的项目列表,如何从循环中查找当前项目的索引

例如:

$letters = { 'A', 'B', 'C' }

$letters | % {
  # Can I easily get the index of $_ here?
}

所有这些的目标是,我希望使用输出一个集合,并使用当前项的索引添加一个初始列。通过这种方式,人们可以交互选择要选择的项目。

我不确定使用“自动”变量是否可行。您始终可以为自己声明一个并递增它:

$letters = { 'A', 'B', 'C' }
$letters | % {$counter = 0}{...;$counter++}
或者对循环使用

for ($counter=0; $counter -lt $letters.Length; $counter++){...}

.NET在System.Array中提供了一些方便的实用方法来实现这类功能:

PS> $a = 'a','b','c'
PS> [array]::IndexOf($a, 'b')
1
PS> [array]::IndexOf($a, 'c')
2
评论中提到了上述方法的优点。除了“只是”在数组中查找项的索引外,考虑到问题的上下文,这可能更合适:

$letters = { 'A', 'B', 'C' }
$letters | % {$i=0} {"Value:$_ Index:$i"; $i++}

Foreach(%)可以有一个执行一次的Begin sciptblock。我们在那里设置了一个索引变量,然后我们可以在进程scripblock中引用它,在退出scriptblock之前它会递增。

对于PowerShell 3.0及更高版本,有一个内置的:)

0..($letters.count-1) | foreach { "Value: {0}, Index: {1}" -f $letters[$_],$_}

对于那些像我一样从谷歌来到这里的人,Powershell的更高版本有一个
$foreach
自动变量。您可以使用
$foreach.current

找到“current”对象,而且您可能不希望在迭代这些项时查找数组项的每个索引。这将是对每一项的线性搜索;听起来像是做了一次迭代O(n^2):-)
IndexOf
如果你确定你总是有一个数组,但是
$letters |%{$i=0}…
方法是安全的,即使
$letters
最后只是一个对象而不是数组。这已经足够干净了,但遗憾的是,没有一种直接方法不涉及在数组中搜索索引。这是查找与数组中每个项匹配的第一个项的索引,而不是使用索引值进行迭代。这是比较慢的,如果数组包含重复的项,您将得到错误的索引。例如:
>“A,B,C,D,E,F,G”-split”,“|%{$i=0}{{if($i-gt 3){${$};++$i}
输出:
efg
当我不得不用计数器重命名文件时,它就像一个魔咒
The
$letters |%{$counter…
选项是安全的,即使
$letters
只是一个对象,而不是一个数组,因为
for
选项不能正确处理它。为此,我从未见过在foreach后面有两组花括号的语法。它解决了这样匹配两个数组的问题:
$selected=$true,$false,$true;@('first'、'second'、'third')|%{$i=0}{If($selected[$i]){$\u};$i++}
返回'first'和'third',这是每个对象的“快捷方式”-开始{first block}-处理{second block}。第一个块在处理前运行一次,第二个块对要处理的每个项目运行一次。有关更多信息,请参阅get help foreach item-full大多数人对当前对象使用
$\uucode>。此外,OP的问题是查找当前对象的索引,而不是对象本身。
foreach ($item in $array) {
    $array.IndexOf($item)
}