Вложенная структура данных OrderedDictionary & Array с New-Object - PullRequest
0 голосов
/ 25 января 2019

Я разработал структуру данных для вложенного словаря, чтобы создать список файлов для работы с ними позже в коде. В настоящее время я успешно использую это для создания пустой структуры данных.

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

Оба не могут преобразовать хеш-таблицу в упорядоченный словарь. Является ли мой единственный вариант чем-то ужасным (IMO), подобным этому

$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 Ответ

0 голосов
/ 25 января 2019

Полагаю, обратная совместимость никогда не бывает красивой?Это лучшее, что я могу придумать, приближаясь к структурированному определению (используя простой массив):

$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))
)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...