Powershell在foreach循环中更新哈希表值?

ted*_*ted 33 powershell

我正在尝试遍历哈希表并将每个键的值设置为5,并且Powershell给出错误:

$myHash = @{}
$myHash["a"] = 1
$myHash["b"] = 2
$myHash["c"] = 3

foreach($key in $myHash.keys){
    $myHash[$key] = 5
}
Run Code Online (Sandbox Code Playgroud)

通过集合枚举时发生错误:

Collection was modified; enumeration operation may not execute..
At line:1 char:8
+ foreach <<<< ($key in $myHash.keys){
    + CategoryInfo          : InvalidOperation: (System.Collecti...tableEnumer
   ator:HashtableEnumerator) [], RuntimeException
    + FullyQualifiedErrorId : BadEnumeration
Run Code Online (Sandbox Code Playgroud)

给出了什么以及如何解决?

And*_*ykh 48

枚举时不能修改Hashtable.这是你可以做的:

$myHash = @{}
$myHash["a"] = 1
$myHash["b"] = 2
$myHash["c"] = 3

$myHash = $myHash.keys | foreach{$r=@{}}{$r[$_] = 5}{$r}
Run Code Online (Sandbox Code Playgroud)

编辑1

这对你来说更简单:

$myHash = @{}
$myHash["a"] = 1
$myHash["b"] = 2
$myHash["c"] = 3

foreach($key in $($myHash.keys)){
    $myHash[$key] = 5
}
Run Code Online (Sandbox Code Playgroud)

  • @JasonMArcher:现在我同意你的意见,但是为了争论,你不认为,如果你在迭代中添加/删除集合中的项目,那么你所描述的内容很可能会发生.这在逻辑上不应该是一个值替换另一个值的问题?在第二个想法,使用Hashtable,更改值,意味着存储的对象可能需要移动到另一个存储桶,并记住这一点,这种行为是有道理的. (2认同)

小智 16

有一种更简单的方法来实现这一目标.您可以在枚举时更改哈希表的值,因为它是一个引用类型变量.这与.Net中的故事完全相同.

使用以下语法来解决它.我们在这里做的是使用@()表示法将密钥集合转换为基本数组.我们制作了密钥集合的副本,并引用该数组,这意味着我们现在可以编辑哈希表.

$myHash = @{}
$myHash["a"] = 1
$myHash["b"] = 2
$myHash["c"] = 3

foreach($key in @($myHash.keys)){
    $myHash[$key] = 5
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您描述为什么使用 @() 运算符。它出现在另一个答案中,但他们没有解释发生了什么。 (2认同)

iRo*_*Ron 6

您不需要为此示例克隆整个哈希表,只需通过将密钥集强制为数组来枚举密钥集@(...)就足够了:

__PRE__


Emi*_*ggi 5

使用clone

foreach($key in ($myHash.clone()).keys){
    $myHash[$key] = 5
}

或者在单线中:

$myHash = ($myHash.clone()).keys | % {} {$myHash[$_] = 5} {$myHash}