2015-06-01 4 views
1

У меня есть хэш-таблица со значениями, которые представляют собой сочетание объектов int и string (иногда строкового массива). Я хочу преобразовать их все в строки, но я не знаю простого способа сделать это без «перестройки» хэш-таблицы, конвертируя каждое значение в строку. Есть ли более простой и эффективный способ сделать это, не зацикливая значения?Преобразование значений Hashtable на месте

Вот простой пример. Это хэш, который я хотел бы преобразовать:

PS C:\Users\me> $test | Select -ExpandProperty Values | % { $_.GetType() } 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
True  True  String         System.Object 
True  True  String         System.Object 
True  True  String         System.Object 
True  True  Int32         System.ValueType 
True  True  Int32         System.ValueType 
True  True  Int32         System.ValueType 

Для этого:

PS C:\Users\gross> $new_test | Select -ExpandProperty Values | % { $_.GetType() } 

IsPublic IsSerial Name          BaseType 
-------- -------- ----          -------- 
True  True  String         System.Object 
True  True  String         System.Object 
True  True  String         System.Object 
True  True  String         System.Object 
True  True  String         System.Object 
True  True  String         System.Object 

ответ

1

Я не думаю, что существует «более эффективный» способ изменения значений. Вы можете установить значения каждой клавиши для значения нового типа ($hash[$key] = $hash[$key].ToString()), но это сложно, если вы зацикливаете, потому что вы меняете объект, который перечисляется.

Вы можете обойти эту проблему в Hacky способом, убедившись, что вы перечислить через копию ключей Хеш, но затем изменить хэш с этим:

$hash = @{ 
    a = '1' 
    b = 2 
    c = 3 
    d = '4' 
    e = 5 
} 

Write-Host "`nBefore:`n" 

$hash.Values | ForEach-Object { $_.GetType() } 

$keys = [Array]::CreateInstance([String], $hash.Keys.Count) 
$hash.Keys.CopyTo($keys, 0) | Out-Null 


$keys | ForEach-Object { 
    $hash[$_] = $hash[$_].ToString() 
} 

Write-Host "`nAfter:`n" 

$hash.Values | ForEach-Object { $_.GetType() } 

Но если честно, Я думаю, что проще просто создать новый:

$hash = @{ 
    a = '1' 
    b = 2 
    c = 3 
    d = '4' 
    e = 5 
} 

Write-Host "`nBefore (`$hash):`n" 

$hash.Values | ForEach-Object { $_.GetType() } 

$newhash = @{} 
$hash.Keys | ForEach-Object { $newhash[$_] = $hash[$_].ToString() } 

Write-Host "`nAfter (`$newhash):`n" 

$newhash.Values | ForEach-Object { $_.GetType() } 
1

Кастинг их строк должно хватить:

$($new_test.Keys) | % { $new_test[$key] = [string]$new_test[$key] } 

или (если вы не» t хотеть отличать все значения без разбора):

($new_test.Keys | ? { $new_test[$_] -is [int] }) | 
    % { $new_test[$key] = [string]$new_test[$key] } 
+0

Я пробовал что-то подобное и получил «Произошла ошибка при перечислении через коллекцию: коллекция была изменена; операция перечисления не может выполняться. ', отсюда мой ответ. Я что-то пропустил? – briantist

+1

Вам нужно развернуть ключи в подвыражении, чтобы отделить это от изменения хеш-таблицы. –

+0

ahh получил. Я закончил создание нового массива окольным путем. Подвыражение намного чище. – briantist

Смежные вопросы