1

我一直在开发一个嵌套字典数据结构来构建一个文件列表,以便稍后在代码中使用。目前我正在成功地使用它来创建空数据结构。

$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(不要问)所以我不能使用 [ordered] 类型。

我努力了

[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] 让我想到-property 可能是答案,这似乎很接近

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

但它无法创建嵌套键、extra、skip 等。我是朝着正确的方向前进,还是我最好承认一堆单独的 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:不。我错了。这实际上使得$assets 变量的内容相同$manageLocalAssets.resources$manageLocalAssets.definitions看来我还在找。

4

1 回答 1

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))
)))
于 2019-01-25T11:56:25.453 回答