如何在 PowerShell 中反向遍历嵌套哈希表

How to reverse traverse a nested hashtable in PowerShell

在上一个问题中,我得到了。不幸的是我忽略了安全组的应用

旧哈希table和工作函数

$Departments = @{
    'Sales' = @{
        'SAM' = 'Manager'
        'SAP' = 'Person'
    }
    'IT'    = @{
        'ITM' = 'Manager'
        'ITS' = 'Specialist'
        'ITT' = 'Technician'
        'ITC' = 'Consultant'     
    }
}

function Get-DepartmentOU {
    Param (
        [CmdletBinding()]
        [Parameter(Mandatory = $true)]
        [System.String]
        $RoleCode
    )

    # Get the DictionaryEntry in the main Hashtable where the nested Hashtable value matches the role you are looking for.
    $Department = $script:Departments.GetEnumerator() | Where-Object { $_.Value.ContainsKey($RoleCode) }

    # Print the name of the DictionaryEntry (Your department) and retrieve the value from the Hashtable for the role.
    "Department: $($Department.Name) Job Title: $($Department.Value[$RoleCode])" 

}


$JobCode = "SAM"
$DepartmentInfo = Get-DepartmentOU -RoleCode $JobCode
$DepartmentInfo

输出Department: Sales Job Title: Manager

上面的效果很好,但是我现在创建了一个更深的散列table并且需要做同样的事情,只是另一个级别来提取更多信息。

新哈希table

$Departments = @{
    "Parts" = @{
        "SG-Parts" = @{
            "PAM" = "Parts Manager"
            "PAA" = "Parts Advisor"
        }
    }
    "Sales" = @{
        "SG-Sales"          = @{
            "SAP" = "Sales Person"
            "SAR" = "Receptionist"
        }
        "SG-Sales Managers" = @{
            "SGM" = "General Manager"
            "SAM" = "Sales Manager"
        }

    }
}

我应该如何更改工作功能以显示按键中包含的文本

输出SG: SG-Sales Managers Department: Sales Job Title: Manager


这可能有助于可视化@mathias-r.-jessen 的 'flat role table/map' 代码生成的数据结构:

$Rolemap = @{
    "PAC" = @{
        "Title"      = "Parts Consultant"
        "SG"         = "SG-Parts"
        "Department" = "Parts"
    }
    "PAA" = @{
        "Title"      = "Parts Advisor"
        "SG"         = "SG-Parts"
        "Department" = "Parts"
    }
    "SGM" = @{
        "Title"      = "General Manager"
        "SG"         = "SG-Sales Managers"
        "Department" = "Sales"
    }
}

原始数据结构模仿了常见的小型 Active Directory 设置,因此人们可以根据需要更快地进行修改。

使用原始数据格式时,每次添加新角色只需添加到散列table中正确的'group'。但是,将 "SAM" = "Sales Manager" 反转为 "Sales Manager"="SAM" 可能有助于提高易读性和逻辑/结构。

我使用 $RoleMap |Format-Custom 和一些手动输入来构建生成的 table 可视化文本。

根据您的 OU-like 散列table 结构创建一个新的平面角色 table:

$RoleMap = @{}

foreach($departmentCode in $Departments.psbase.Keys){
    foreach($sgCode in $Departments[$departmentCode].psbase.Keys){
        foreach($roleCode in $Departments[$departmentCode][$sgCode].psbase.Keys){
            # Create a summary object that includes all 3 pieces of information
            # Store in role table and use the "role code" as the key
            $RoleMap[$roleCode] = [pscustomobject]@{
                Title = $Departments[$departmentCode][$sgCode][$roleCode]
                SG = $sgCode
                Department = $departmentCode
            }
        }
    }
}

现在解析角色代码时可以完全避免...GetEnumerator() | Where-Object { ... }:

function Get-DepartmentOU {
    param(
        [CmdletBinding()]
        [Parameter(Mandatory = $true)]
        [string]
        $RoleCode
    )

    if($script:RoleMap.Contains($RoleCode)){
        # `Where-Object` no longer needed!
        $roleDescription = $script:RoleMap[$RoleCode]

        "SG: $($roleDescription.SG) Department: $($roleDescription.Name) Job Title: $($roleDescription.Title)"
    }
}