Skip to content

Instantly share code, notes, and snippets.

@edxi
Last active November 30, 2021 09:20
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edxi/87cb8a550b43ec90e4a89d2e69324806 to your computer and use it in GitHub Desktop.
Save edxi/87cb8a550b43ec90e4a89d2e69324806 to your computer and use it in GitHub Desktop.
Compare-Hashtable
function Compare-Hashtable {
<#
.SYNOPSIS
Compare two Hashtable and returns an array of differences.
.DESCRIPTION
The Compare-Hashtable function computes differences between two Hashtables. Results are returned as
an array of objects with the properties: "key" (the name of the key that caused a difference),
"side" (one of "<=", "!=" or "=>"), "lvalue" an "rvalue" (resp. the left and right value
associated with the key).
.PARAMETER left
The left hand side Hashtable to compare.
.PARAMETER right
The right hand side Hashtable to compare.
.EXAMPLE
Returns a difference for ("3 <="), c (3 "!=" 4) and e ("=>" 5).
Compare-Hashtable @{ a = 1; b = 2; c = 3 } @{ b = 2; c = 4; e = 5}
.EXAMPLE
Returns a difference for a ("3 <="), c (3 "!=" 4), e ("=>" 5) and g (6 "<=").
$left = @{ a = 1; b = 2; c = 3; f = $Null; g = 6 }
$right = @{ b = 2; c = 4; e = 5; f = $Null; g = $Null }
Compare-Hashtable $left $right
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Hashtable]$Left,
[Parameter(Mandatory = $true)]
[Hashtable]$Right
)
function New-Result($Key, $LValue, $Side, $RValue) {
New-Object -Type PSObject -Property @{
key = $Key
lvalue = $LValue
rvalue = $RValue
side = $Side
}
}
[Object[]]$Results = $Left.Keys | % {
if ($Left.ContainsKey($_) -and !$Right.ContainsKey($_)) {
New-Result $_ $Left[$_] "<=" $Null
} else {
if ($Left[$_] -is [hashtable] -and $Right[$_] -is [hashtable] ) {
Compare-Hashtable $Left[$_] $Right[$_]
}
else {
$LValue, $RValue = $Left[$_], $Right[$_]
if ($LValue -ne $RValue) {
New-Result $_ $LValue "!=" $RValue
}
}
}
}
$Results += $Right.Keys | % {
if (!$Left.ContainsKey($_) -and $Right.ContainsKey($_)) {
New-Result $_ $Null "=>" $Right[$_]
}
}
if ($Results -ne $null) { $Results }
}
@spaceygithub
Copy link

spaceygithub commented Feb 14, 2018

Managed to work it out with help from else where... Code if your interested is here... This tracks the Key/Path as it walks the hashes.

     function Compare-Hashtable {
     [CmdletBinding()]
    param (
    [Parameter(Mandatory = $true)]
    [Hashtable]$Left,

    [Parameter(Mandatory = $true)]
    [Hashtable]$Right,
    [string[]] $path,
    [boolean] $trackpath = $True
)
write-host "Path received as: $path"
function New-Result($Path, $LValue, $Side, $RValue) {
    New-Object -Type PSObject -Property @{
        key    = $Path -Join "/"
        lvalue = $LValue
        rvalue = $RValue
        side   = $Side
    }
}

$Left.Keys | ForEach-Object {
    write-host "*** " $_
    $NewPath = $Path + $_
    if ($trackpath ) {
        write-host "Working on Path: " $NewPath
    }

    if ($Left.ContainsKey($_) -and !$Right.ContainsKey($_)) {
        write-host "Right key not matched. Report path as: $NewPath"
        New-Result $NewPath $Left[$_] "<=" $Null
    }
    else {
        if ($Left[$_] -is [hashtable] -and $Right[$_] -is [hashtable] ) {
             Compare-Hashtable $Left[$_] $Right[$_] $NewPath
        }
        else {
            $LValue, $RValue = $Left[$_], $Right[$_]
            if ($LValue -ne $RValue) {
                New-Result $NewPath $LValue "!=" $RValue
            }
         }

    }
}
$Right.Keys | ForEach-Object {
    $NewPath = $Path + $_
    if (!$Left.ContainsKey($_) -and $Right.ContainsKey($_)) {
        New-Result $NewPath $Null "=>" $Right[$_]

    }
}
 } 
  Compare-Hashtable $Sailings $Flights      

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment