Powershell在循环中获取枚举器

问题描述 投票:2回答:2

我正在尝试在循环哈希表时获取枚举器。

我确实理解它在foreach循环中是如何工作的,如下所示:

$test = @{set01 = '0'; set02 = '1'}
foreach ($t in $test.GetEnumerator()) {
    Write-Host 'key: '$t.Key
}

哪个会循环输出单个键:

key:  set02
key:  set01

我想知道是否可以在C类型循环中执行此操作,例如:

$test = @{set01 = '0'; set02 = '1'}
for ($i = 0; $i -lt 1; $i++) {
    Write-Host 'key: '$test.Keys[$i] # edited with Dandré's answer.
}

其中列出了所有键:

key:  set02 set01
key:  

这是可能的还是.GetEnumerator()只能在foreach情况下工作?

编辑:阅读mklement0's答案我发现它不是直接可能的。我会将其标记为详细解释的答案。

我想出一个解决方法来提取循环位置的关键字部分链接到Dandré's答案结合mklement0的解释。

如果在运行循环之前将密钥收集到数组中,则可以在运行for循环时查找它们。

$test = @{set01 = '0'; set02 = '1'}

$keys = @($test.Keys)

for ($i = 0; $i -lt $test.Count; $i++) {
    Write-Host 'key:'$keys[$i]
}

这将按预期结果:

key: set02
key: set01

根据数组,键需要首先逆转[array]::Reverse($keys)

$keys变量也可以在循环中用于调用特定键,如:$test[$keys[$i]]。这有点像黑客,但开启了一些有趣的可能性。

powershell hashtable enumeration
2个回答
2
投票

您正在创建一个哈希表,无法使用位置索引访问其条目(01,...);相反,你在[...]中指定的是一个输入键。

因此,使用.Keys属性进行枚举:

$test = @{set01 = '0'; set02 = '1'}
foreach ($key in $test.Keys) {
  $key 
  # To access the entry's *value*, use $test[$key] $test[$key]
}

结果是:

set02
set01

请注意密钥的枚举方式与定义的顺序不同,因为[hashtable]实例不保证任何特定的枚举顺序。

在PSv3 +中,您可以使用有序的哈希表来解决这个问题,这也可以让您使用位置索引 - 但请注意,位置索引会返回条目值,而不是键:

$test = [ordered] @{set01 = '0'; set02 = '1'}
for ($i = 0; $i -lt $test.Count; $i++) {
  $test[$i]
}

注意:虽然你可以使用$test.Keys[$i]来访问密钥,就像在Dandre's answer中一样,使用foreach ($key in $test.Keys)直接枚举密钥不那么冗长和快速;使用$test.Keys[$i]进行基于索引的迭代的唯一理由是,如果索引$i不仅仅是一个辅助变量,而且是操作所必需的,例如输出反映键及其索引的字符串。

因此上述产量:

0
1

请注意,for语法不仅详细,它实际上比foreach表现更差,如果你确实需要显式索引,请使用foreach和通过范围运算符生成的索引(..),这不仅更快,而且可以说更具可读性比for循环:

$test = [ordered] @{set01 = '0'; set02 = '1'}
foreach ($i in 0..($test.Count-1)) {
   $test[$i]
}

虽然它的内存效率较低,但由于索引数组必须作为一个整体预先创建,因此通常不需要考虑。


3
投票

同意@ mklement0。如果你想要传统的for循环,你可以使用Keys属性执行以下操作。

$test = @{set01 = '0'; set02 = '1'}

for ($i = 0; $i -lt $test.Count; $i++) {
    Write-Host $test.Keys[$i]
}

这将输出:set02 set01

© www.soinside.com 2019 - 2024. All rights reserved.