Internal/_MergeHashtables.ps1

function _MergeHashtables {
    <#
    .SYNOPSIS
    Merges two hashtables together and returns the result
 
    .DESCRIPTION
    When adding two hashes together, an error will be thrown if there are duplicate keys in the table.
 
    The order in which the hashtables are passed to the function is very important. So the primary hashtable
    will be the master, and keys that exist here will override the same one in the secondary hashtable.
 
    The only exception to this is that the system will determine if both keys are another hashtable. If they are
    then the function is called recursively again to provide the merged tables
 
    Credit
    Originally taken from the following page: http://jdhitsolutions.com/blog/2013/01/join-powershell-hash-tables
    #>

    [cmdletbinding()]
    Param (
        [hashtable]
        # First hashtable to merge, this will have priority
        $Primary,

        [hashtable]
        # second hashtable to merge
        $Secondary
    )

    # Do not touch the original hashtables
    #$PrimaryClone = $primary.Clone()
    #$SecondaryClone = $secondary.Clone()
    $primaryClone = _CopyObject -DeepCopyObject $Primary
    $secondaryClone = _CopyObject -DeepCopyObject $Secondary

    # Create an array of types that can be merged.
    # Hashtables and Dictionaries can be merged
    $types = @(
        "Hashtable"
        "Dictionary"
    )

    # Check for any duplicate keys
    $duplicates = $primaryClone.keys | where {$secondaryClone.ContainsKey($_)}

    if ($duplicates) {
        foreach ($key in $duplicates) {

            # If the item is a hashtable then call this function again
            if ($types -contains $primaryClone.$key.gettype().name -and
                $types -contains $secondaryClone.$key.gettype().name) {
                $splat = @{
                    primary = $primaryClone.$key
                    secondary = $secondaryClone.$key
                }
                $primaryClone.$key = _MergeHashtables @splat
            }
                
            <#
            # If the key is an array merge the two items
            if ($PrimaryClone.$key.GetType().Name -eq "Object[]" -and $SecondaryClone.$key.GetType().name -eq "Object[]") {
 
                $result = @()
 
                # Because an array can contain many different types, need to be careful how this information is merged
                # This means that the normal additional functions and the Unique parameter of Select will not work properly
                # so iterate around each of the two arrays and add to a result array
                foreach ($arr in @($PrimaryClone.$key, $SecondaryClone.$key)) {
 
                    # analyse each item in the arr
                    foreach ($item in $arr) {
 
                        # Switch on the type of the item to determine how to add the information
                        switch ($item.GetType().Name) {
                            "Object[]" {
                                $result += , $item
                            }
 
                            # If the type is a string make sure that the array does not already
                            # contain the same string
                            "String" {
                                if ($result -notcontains $item) {
                                    $result += $item
                                }
                            }
 
                            # For everything else add it in
                            default {
                                $result += $item
                            }
                        }
                    }
                }
 
                # Now assign the result back to the primary array
                $PrimaryClone.$key = $result
            }
            #>


            # Force primary key, so remove secondary conflict
            $secondaryClone.Remove($key)
        }
    }

    # Join the two hash tables and return to the calling function
    return ($primaryClone + $secondaryClone)
}