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

时间:2022-10-25 09:11:34

I'm trying to loop through a hash table and set the value of each key to 5 and Powershell gives an error:

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

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

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

An error occurred while enumerating through a collection:

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

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

What gives and how do I resolve?

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

8 个解决方案

#1


42  

You can't modify Hashtable while enumerating it. This is what you can do:

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

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

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

Edit 1

编辑1

Is this any simpler for you:

这对你来说更简单:

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

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

#2


11  

there is a much simpler way of achieving this. You cannot change the value of a hashtable whilst enumerating it because of the fact that it's a reference type variable. It's exactly the same story in .Net.

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

Use the following syntax to get around it. What we are doing here is converting the keys collection into a basic array using @() notation. We make a copy of the keys collection, and reference that array instead which means we can now edit the hashtable.

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

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

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

#3


4  

You do not need to clone the whole hashtable for this example, just enumerating the key collection by forcing it to an array @(...) is enough:

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

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

#4


3  

Use clone:

使用克隆:

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

or in the one-liner:

或在单行中:

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

#5


2  

I'm new to PowerShell, but I'm quite a fan of using in-built functions, because I find it more readable. This is how I would tackle the problem, using GetEnumerator and Clone. This approach also allows one to reference to the existing hash values ($_.value) for modifying purposes.

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

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

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

#6


2  

You have to get creative!

你必须有创意!

$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       

#7


0  

Seems when you update the hash table inside the foreach, the enumerator invalidates itself. I got around this by populating a new hash table:

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

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

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

#8


0  

As mentioned above, clone is the way to go. I had a need to replace any null values in a hash with "Unknown" nd this one-liner does the job.

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

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

#1


42  

You can't modify Hashtable while enumerating it. This is what you can do:

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

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

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

Edit 1

编辑1

Is this any simpler for you:

这对你来说更简单:

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

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

#2


11  

there is a much simpler way of achieving this. You cannot change the value of a hashtable whilst enumerating it because of the fact that it's a reference type variable. It's exactly the same story in .Net.

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

Use the following syntax to get around it. What we are doing here is converting the keys collection into a basic array using @() notation. We make a copy of the keys collection, and reference that array instead which means we can now edit the hashtable.

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

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

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

#3


4  

You do not need to clone the whole hashtable for this example, just enumerating the key collection by forcing it to an array @(...) is enough:

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

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

#4


3  

Use clone:

使用克隆:

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

or in the one-liner:

或在单行中:

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

#5


2  

I'm new to PowerShell, but I'm quite a fan of using in-built functions, because I find it more readable. This is how I would tackle the problem, using GetEnumerator and Clone. This approach also allows one to reference to the existing hash values ($_.value) for modifying purposes.

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

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

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

#6


2  

You have to get creative!

你必须有创意!

$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       

#7


0  

Seems when you update the hash table inside the foreach, the enumerator invalidates itself. I got around this by populating a new hash table:

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

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

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

#8


0  

As mentioned above, clone is the way to go. I had a need to replace any null values in a hash with "Unknown" nd this one-liner does the job.

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

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