Search code examples
powershellforeachcomparehashtable

How to select a particular hashtable key and value while comparing two hashtables with Powershell?


I need to compare and merge two hash tables, but retain the value of a specific key.

$Left = @{Name = "Alex"; CreationDate = "2018-10-20"; Status = "Married"}
$Right = @{CreationDate = "2019-03-15"; Status = "Divorced"; City = "NY"; Country = "US"}

Once those two are merged, the Name should not be changed, the CreationDate has to remain "2001-10-20" as in the $Left table, the Status needs to be updated, and the City and Country should be appended to the list. The following script is properly updating, adding and retaining the values for all the keys, but it overrides my CreationDate.

This is for updating some file tags using Powershell.

function New-Result($Key, $Value) {
        New-Object -Type PSObject -Property @{
                    Key    = $Key
                    Value = $Value
            }
    }
    [Object[]]$Results = $Left.Keys | % {
        if ($Left.ContainsKey($_) -and !$Right.ContainsKey($_)) {
            New-Result $_ $Left[$_]
        }
    }
    $Results += $Right.Keys | % {
        if (!$Left.ContainsKey($_) -and $Right.ContainsKey($_) -and ($Right[$_])){
                New-Result $_ $Right[$_]

        }
    }

    $Results += $Right.Keys | % {
        if ($Left.ContainsKey($_) -and $Right.ContainsKey($_) -and ($Right[$_])) {
            New-Result $_ $Right[$_]
        } 
    }
    return $Results 

I need to pick the $Left value for the CreationDate key, but am unable to do it so far.


Solution

  • this is rather homely, but it works. [grin]

    what it does ...

    • iterates thru the keys in the new version of the table
    • if the key is Status, update the old version with the new value
    • if the key is not in the list of keys in the old version, add it and its value

    since hashtables are passed by reference, you can put this in a function if needed. i am not sure that it makes sense to do so, tho. i would likely put it in a loop to handle the items in your collection.

    the code ...

    $Original = @{
        Name = "Alex"
        CreationDate = "2018-10-20"
        Status = "Married"
        }
    $Updated = @{
        CreationDate = "2019-03-15"
        Status = "Divorced"
        City = "NY"
        Country = "US"
        }
    
    foreach ($Key in $Updated.Keys)
        {
        if ($Key -eq 'Status')
            {
            $Original[$Key] = $Updated[$Key]
            }
        if ($Key -notin $Original.Keys)
            {
            $Original.Add($Key, $Updated[$Key])
            }
        }
    
    $Original
    

    output ...

    Name                           Value
    ----                           -----
    CreationDate                   2018-10-20
    Status                         Divorced
    Name                           Alex
    City                           NY
    Country                        US