web-dev-qa-db-fra.com

Powershell met-il à jour les valeurs de la table de hachage dans une boucle foreach?

J'essaie de parcourir une table de hachage et de définir la valeur de chaque clé sur 5 et Powershell génère une erreur:

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

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

Une erreur s'est produite lors de l'énumération dans une 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

Que donne et comment puis-je résoudre?

31
ted

Vous ne pouvez pas modifier Hashtable en l'énumérant. Voici ce que vous pouvez faire:

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

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

Modifier 1

Est-ce plus simple pour vous:

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

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

il existe un moyen beaucoup plus simple d'y parvenir. Vous ne pouvez pas modifier la valeur d'une table de hachage lors de son énumération, car il s'agit d'une variable de type référence. C'est exactement la même histoire en .Net. 

Utilisez la syntaxe suivante pour le contourner. Ce que nous faisons ici est de convertir la collection de clés en un tableau de base en utilisant la notation @ (). Nous faisons une copie de la collection de clés et référençons ce tableau, ce qui signifie que nous pouvons maintenant éditer la table de hachage.

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

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

Utilisez clone:

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

ou dans le one-liner:

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

Vous devez être créatif!

$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       
2
ScubaZip

Je suis nouveau dans PowerShell, mais je suis assez fan des fonctions intégrées, car je le trouve plus lisible. C’est ainsi que j’aurais résolu le problème en utilisant GetEnumerator et Clone. Cette approche permet également de faire référence aux valeurs de hachage existantes ($ _. Valeur) à des fins de modification.

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

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

Comme mentionné ci-dessus, le clone est la voie à suivre. J'avais besoin de remplacer les valeurs NULL dans un hachage par "Unknown" et ce one-liner fait le travail.

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