Search code examples
powershellmergehashtable

Combine two dictionaries and replace keys with values in powershell


i have two arrays that look like this:

$ht1 = @{

"computer55" = "port33"

“computer1” = “port1”

“computer2” = “port2”



}

and

$ht2 = @{

"A1:B2:C3:D4:E5:F6" = "port1"

"A2:B3:C4:D5:E6:F7" = "port2"

"A3:B4:C5:D6:E7:F8" = "port33"

"A4:B4:C5:D6:E7:F8" = "port45"
}

The first one is one I manually hardcode into the script, I have an actual list of device names and what port they are plugged into on a switch. The second one is generated with a switch script that logs in, gets the mac address table and records it as a hashtable.

My desired outcome is this, if there is a port with an assigned name, replace the port name with the device name.

$ht3(or any name) = @{

"A1:B2:C3:D4:E5:F6" = "computer1"

"A2:B3:C4:D5:E6:F7" = "computer2"

"A3:B4:C5:D6:E7:F8" = "computer55"

"A4:B4:C5:D6:E7:F8" = "port45"
}

I've somehow spent about a day on this(... pretty much the first powershell script I've ever came up with) and my end result is always the same, I end up merging two hashtables and pair the port with the computer name and not the mac address with the computer name. any direction is appreciated


Solution

  • Important note, the .ContainsValue method is case sensitive, if you want a case insensitive search use one of the following:

    if($val = [string]$ht1.Keys.Where({$ht1[$_] -eq $ht2[$key]}))
    {
        @{$key = $val}
        continue
    }
    
    if($ht1.Values -contains $ht2[$key])
    {
        ...
    }
    
    if($ht2[$key] -in $ht1.Values)
    {
       ...
    }
    

    Code

    $ht1 = @{
        computer55 = 'port33'
        computer1 = 'port1'
        computer2 = 'port2'
    }
    
    $ht2 = @{
        'A1:B2:C3:D4:E5:F6' = 'port1'
        'A2:B3:C4:D5:E6:F7' = 'port2'
        'A3:B4:C5:D6:E7:F8' = 'port33'
        'A4:B4:C5:D6:E7:F8' = 'port45'
    }
    
    $result = foreach($key in $ht2.Keys)
    {
        if($ht1.ContainsValue($ht2[$key]))
        {
            @{$key = [string]$ht1.Keys.Where({$ht1[$_] -eq $ht2[$key]})}
            continue
        }
        @{$key = $ht2[$key]}
    }
    

    Looking at $result yields:

    Name                           Value      
    ----                           -----      
    A1:B2:C3:D4:E5:F6              computer1  
    A3:B4:C5:D6:E7:F8              computer55 
    A4:B4:C5:D6:E7:F8              port45     
    A2:B3:C4:D5:E6:F7              computer2  
    

    [string]$ht1.Keys.Where({$ht1[$_] -eq $ht2[$key]})
    

    Could also be the following, though, I'm not sure which one would be more efficient:

    $ht1.GetEnumerator().Where({$_.Value -eq $ht2[$key]}).Key