Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to reverse traverse a nested hashtable in PowerShell

In a previous question, I was given a solution for finding the name of a key by its value. Unfortunately I neglected to consider the application of Security Groups

Old hashtable and working function

$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

OUTPUT: Department: Sales Job Title: Manager

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

The above works excellently, however I’ve now created a deeper hashtable and need to do the same thing, just another level to extract more information.

New hashtable

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

    }
}

How should I change the working function to display the text contained in the key

OUTPUT: SG: SG-Sales Managers Department: Sales Job Title: Manager

>Solution :

Create a new flat role table from your OU-like hashtable structure:

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

Now you can avoid ...GetEnumerator() | Where-Object { ... } completely when resolving the role code:

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)"
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading