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

时间:2011-05-04 07:18:03

标签: powershell

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

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

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

枚举集合时发生错误:

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

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

10 个答案:

答案 0 :(得分:44)

枚举时,您无法修改Hashtable。这就是你能做的:

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

$myHash = $myHash.keys | foreach{$r=@{}}{$r[$_] = 5}{$r}

修改1

这对你来说更简单:

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

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

答案 1 :(得分:12)

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

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

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

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

答案 2 :(得分:5)

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

foreach($key in @($myHash.keys)){...

答案 3 :(得分:3)

使用clone

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

或在单行中:

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

答案 4 :(得分:2)

我是PowerShell的新手,但我非常喜欢使用内置函数,因为我发现它更具可读性。这就是我使用GetEnumerator和Clone解决问题的方法。此方法还允许人们引用现有的哈希值($ _。value)以进行修改。

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

$myHash.Clone().GetEnumerator() | foreach-object {$myHash.Set_Item($_.key, 5)}

答案 5 :(得分:2)

你必须有创意!

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

$keys = @()
[array] $keys = $myHash.keys

foreach($key in $keys)
    {
    $myHash.Set_Item($key, 5)
    }

$myHash

Name                         Value                                                                                                                                                                                                   
----                         -----                                                                                                                                                                                                   
c                              5                                                                                                                                                                                                       
a                              5                                                                                                                                                                                                       
b                              5       

答案 6 :(得分:0)

如上所述,克隆是最佳选择。我需要用“未知”替换散列中的任何空值,并且这个单行程可以完成这项工作。

($record.Clone()).keys| %{if ($record.$_ -eq $null) {$record.$_ = "Unknown"}}

答案 7 :(得分:0)

$myHash = @{
    Americas = 0;
    Asia = 0;
    Europe = 0;
}

$countries = @("Americas", "Asia", "Europe", "Americas", "Asia")

foreach($key in $($myHash.Keys))
{
    foreach($Country in $countries)
    {
        if($key -eq $Country)
        {
            $myHash[$key] += 1
        }
    }
}

$myHash

答案 8 :(得分:0)

$myHash = @{
    Americas = 0;
    Asia = 0;
    Europe = 0;
}

$countries = @("Americas", "Asia", "Europe", "Americas", "Asia")

foreach($key in $($myHash.Keys))
{
    foreach($Country in $countries)
    {
        if($key -eq $Country)
        {
            $myHash[$key] += 1
        }
    }
}

如果数组元素与哈希键匹配,则更新哈希值。

答案 9 :(得分:-1)

当您更新foreach中的哈希表时,枚举器会使自身无效。我通过填充一个新的哈希表来解决这个问题:

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

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