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


69

给定PowerShell中的项目列表,如何在循环中找到当前项目的索引?

例如:

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

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

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

Answers:


53

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

$letters = { 'A', 'B', 'C' }
$letters | % {$counter = 0}{...;$counter++}

for改为使用循环...

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

示例:> "A,B,C,D,E,F,G" -split "," | % { $i = 0 } { if ( $i -gt 3 ) { $_ }; ++$i }输出:E F G
Andrew

当我不得不用一个计数器重命名文件时,它就像一种魅力一样工作dir | % {$i = 46}{ move-item $_ ("ARM-{0:00000}.pdf" -f $i++)}
dance2die 17'Dec

1
$letters | % {$counter...选项是安全的,即使$letters它只是一个对象而不是数组,因为该for选项不能正确处理该对象。
克里斯·马格努森

1
谢谢-我从未见过在foreach之后带有两组花括号的语法。它解决了这样匹配两个数组的问题: $selected = $true,$false,$true; @('first','second','third') | % {$i=0}{If($selected[$i]){$_};$i++ } 返回“第一个”和“第三个”
Rich Moss

1
这是foreach-object -Begin {first block} -Process {second block}的“捷径”。第一个块在处理之前运行一次,第二个对要处理的每个项目运行。见获取帮助的foreach项-full更多信息
塞德里克RUP

69

.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。我们在此处设置一个索引变量,然后可以在流程脚本块中引用它,在退出脚本块之前,该变量会递增。


8
同样,您可能不想在迭代数组项时查找它们的每个索引。这将是对每个项目的线性搜索;听起来像是进行一次迭代O(n ^ 2):-)
乔伊(Joey

IndexOf如果您确定始终都有一个数组,则该$letters | % {$i=0}...方法有效,即使该方法$letters最终只是一个对象而不是数组,该方法也是安全的。
克里斯·马格努森

50

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

foreach ($item in $array) {
    $array.IndexOf($item)
}

34
这是在查找与数组中每个项目匹配的第一个项目的索引,而不是使用索引值进行迭代。这比较慢,并且如果数组包含重复项,则会得到错误的索引。
mdonoughe


-1

对于像我一样来自Google的用户,Powershell的更高版本具有$foreach自动变量。您可以使用以下命令找到“当前”对象$foreach.Current


大多数人使用$_当前对象。另外,OP的问题是关于找到当前对象的索引,而不是对象本身。
Max Cascone
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.