Вложенная структура данных OrderedDictionary & Array с New-Object
Я разрабатывал вложенную словарную структуру данных, чтобы создать список файлов для работы с ними позже в коде. В настоящее время я успешно использую это для создания пустой структуры данных.
$manageLocalAssets = @{
resources = @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
definitions = @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
}
Это работает, но я бы хотел использовать Упорядоченный словарь, а не хеш-таблицы, чтобы я мог просматривать данные в определенном порядке. Кроме того, мне нужно поддерживать PS2.0 (не спрашивайте), поэтому я не могу использовать [заказанный] тип.
я пытался
[Collections.Specialized.OrderedDictionary]$manageLocalAssets = @{
resources = @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
definitions = @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
}
и я попробовал
$manageLocalAssets = [Collections.Specialized.OrderedDictionary]@{
resources = @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
definitions = @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
}
Оба не могут преобразовать хеш-таблицу в упорядоченный словарь. Это мой единственный вариант что-то уродливое (ИМО), как это
$manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary
$manageLocalAssets.Add('resources', (New-Object Collections.Specialized.OrderedDictionary))
$manageLocalAssets.resources.Add('extra', (New-Object Collections.ArrayList))
[ss64][1] заставляет меня задуматься: возможно, ответом будет свойство, и это, кажется, близко
$manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary -property @{
resources = New-Object Collections.Specialized.OrderedDictionary -property @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
definitions = New-Object Collections.Specialized.OrderedDictionary -property @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
}
Но он не может создать вложенные ключи, дополнительные, пропустить и т. Д. Я иду в правильном направлении, или мне лучше просто допустить набор отдельных New-Object и.Add строки - это путь?
РЕДАКТИРОВАТЬ #1: у меня была мысль, так как на самом глубоком уровне структура данных идентична, я попробовал это
$assets = New-Object Collections.Specialized.OrderedDictionary -property @{
extra = New-Object Collections.ArrayList
new = New-Object Collections.ArrayList
skip = New-Object Collections.ArrayList
update = New-Object Collections.ArrayList
}
$manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary -property @{
resources = $assets
definitions = $assets
}
и странные вещи, ошибка
New-Object : The member "skip" was not found for the specified .NET object.
At \\Mac\Support\Px Tools\Dev 4.0\Resources\PxContext_Machine.ps1:413 char:15
+ ... $assets = New-Object Collections.Specialized.OrderedDictionary -pro ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.NewObjectCommand
New-Object : The member "resources" was not found for the specified .NET object.
At \\Mac\Support\Px Tools\Dev 4.0\Resources\PxContext_Machine.ps1:419 char:26
+ ... calAssets = New-Object Collections.Specialized.OrderedDictionary -pro ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.NewObjectCommand
[1]: https://ss64.com/ps/new-object.html
413 является $assets = New-Object Collections.Specialized.OrderedDictionary -property @{
линия, в то время как 419 является $manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary -property @{
линия.
Таким образом, кажется, что дополнительные и новые обрабатываются вначале, затем пропускается неудача в первом назначении, а ресурсы сразу же перестают работать во втором назначении.
РЕДАКТИРОВАНИЕ № 2: Итак, выделение повторяющейся части в качестве другой переменной приведет меня к этому
$assets = New-Object Collections.Specialized.OrderedDictionary
$assets.Add('extra', (New-Object Collections.ArrayList))
$assets.Add('new', (New-Object Collections.ArrayList))
$assets.Add('skip', (New-Object Collections.ArrayList))
$assets.Add('update', (New-Object Collections.ArrayList))
$manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary
$manageLocalAssets.Add('resources', $assets)
$manageLocalAssets.Add('definitions', $assets)
Что на самом деле меньше строк, и будет еще более эффективным, когда я добавлю в $manageLocalAssets. Визуально это не похоже на другие инициализации моей структуры данных, но, думаю, со временем я к этому привыкну. И это позволяет мне использовать такую структуру цикла для работы с данными в нужном порядке.
foreach ($asset in $manageLocalAssets.keys) {
foreach ($key in ($manageLocalAssets.$asset).keys) {
Write-Host "$asset $key"
foreach ($file in $manageLocalAssets.$asset.$key) {
Write-Host " $file"
}
}
}
Не "идеальный", но тогда "идеальный" здесь означает "знакомый", и это не повод принимать решения.
РЕДАКТИРОВАНИЕ № 3: Нет. Я был неправ. Это на самом деле делает содержание обоих $manageLocalAssets.resources
а также $manageLocalAssets.definitions
то же самое, переменная $assets. Кажется, я все еще ищу.
1 ответ
Я полагаю, обратная совместимость никогда не бывает красивой? Это лучшее, что я мог придумать, приблизившись к структурированному определению (используя простой массив):
$definition = ((
"resources", (
"extra",
"new",
"skip",
"update"
)), (
"definitions", (
"extra",
"new",
"skip",
"update"
)))
$manageLocalAssets = New-Object System.Collections.Specialized.OrderedDictionary
$definition | foreach {
$sub = New-Object System.Collections.Specialized.OrderedDictionary
$_[1] | foreach {
$sub.Add($_, (New-Object Collections.ArrayList))
}
$manageLocalAssets.Add($_[0], $sub)
}
Конечно, вы также можете поместить фактические значения (ArrayLists) в определение массива, но я полагаю, что это было бы намного больше, чтобы написать и выглядеть не так красиво.
Альтернативное решение, использующее функцию для создания упорядоченного словаря с переменными уровнями из определения. Несколько более многословный, но многократно используемый:
function New-OrderedDictionary ($definition) {
$dict = New-Object System.Collections.Specialized.OrderedDictionary
foreach ($item in $definition) {
$key, $value = $item[0, 1]
# you might want to change this check,
# depending on how you want to built the definition
if ($value.Count -gt 0) {
$value = New-OrderedDictionary $value
}
$dict.Add($key, $value)
}
return $dict
}
$manageLocalAssets = New-OrderedDictionary ((
"resources", (
("extra" , (New-Object System.Collections.Specialized.OrderedDictionary)),
("new" , (New-Object System.Collections.Specialized.OrderedDictionary)),
("skip" , (New-Object System.Collections.Specialized.OrderedDictionary)),
("update", (New-Object System.Collections.Specialized.OrderedDictionary))
)), (
"definitions", (
("extra" , (New-Object System.Collections.Specialized.OrderedDictionary)),
("new" , (New-Object System.Collections.Specialized.OrderedDictionary)),
("skip" , (New-Object System.Collections.Specialized.OrderedDictionary)),
("update", (New-Object System.Collections.Specialized.OrderedDictionary))
)))