Подтвердить что ты не робот

Обновление значений хеш-таблицы в цикле 'foreach' в 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

Что дает и как мне решить эту проблему?

4b9b3361

Ответ 1

Вы не можете изменить Hashtable при перечислении. Это то, что вы можете сделать:

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

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

Изменить 1

Это проще для вас:

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

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

Ответ 2

Существует гораздо более простой способ достижения этого. Вы не можете изменить значение хеш-таблицы при его перечислении из-за того, что это переменная ссылочного типа. Это точно такая же история в .NET.

Используйте следующий синтаксис, чтобы обойти это. Мы преобразуем коллекцию ключей в базовый массив, используя нотацию @(). Мы делаем копию коллекции ключей и вместо этого ссылаемся на этот массив, что означает, что теперь мы можем редактировать хеш-таблицу.

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

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

Ответ 3

Вам не нужно клонировать всю хеш-таблицу для этого примера. Достаточно просто перечислить коллекцию ключей, поместив ее в массив @(...):

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

Ответ 4

Используйте clone:

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

Или в одну строку:

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

Ответ 5

Я новичок в PowerShell, но я очень люблю использовать встроенные функции, потому что считаю его более читаемым. Вот как я мог бы решить эту проблему, используя GetEnumerator и Clone. Этот подход также позволяет ссылаться на существующие хеш-значения (значение $_.) Для целей изменения.

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

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

Ответ 6

Вы должны стать творческими!

$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

Как упоминалось в предыдущем ответе, clone - это путь. Мне нужно было заменить любые нулевые значения в хэше на "Неизвестно", и этот однострочный выполняет свою работу.

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

Ответ 8

$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

Ответ 9

$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
        }
    }
}

Обновление значения хеша, если элементы массива совпали с ключом хеша.

Ответ 10

Кажется, когда вы обновляете хеш-таблицу внутри цикла foreach, перечислитель делает себя недействительным. Я справился с этим, заполнив новую хеш-таблицу:

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

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