Skip to content

Instantly share code, notes, and snippets.

@pocc
Created February 1, 2019 22:37
Show Gist options
  • Save pocc/1d3679ef585582eb05577c789c53cc5d to your computer and use it in GitHub Desktop.
Save pocc/1d3679ef585582eb05577c789c53cc5d to your computer and use it in GitHub Desktop.
Compare Powershell hash tables recursively
# Compare Powershell hash tables using a helper function.
# Usage:
# PS> Import-Module ./compare_hash_tables.ps1
# PS> $hash1 = @{'1'='2'; '3'=@(@{'5'='8'; 'a'='b'},'7', 'c'); 'd'=@('e')}
# PS> $hash2 = @{'1'='1'; '3'=@(@{'5'='9'},'6'); 'd'=@('e','f')}
# PS> Compare-Hashes $hash1 $hash2
#
# : hash['3'] : list[0] : hash['5'] : <->
# -> Expected '8'
# -> Actually '9'
# : hash['3'] : list[0] : hash['a'] in Expected but not Actual!
# : hash['3'] : list[1] : <->
# -> Expected '7'
# -> Actually '6'
# : hash['3'] : list['c'] in Expected but not Actual!
# : hash['d'] : list['f'] in Actual but not Expected!
# : hash['1'] : <->
# -> Expected '2'
# -> Actually '1'
function Compare-Hashes ($expected, $actual, $history='') {
# Recursively compare hash tables.
# Add a newline before output at recursion level 0
if ($history -eq '') {
Write-Host ""}
$allKeys = $expected.keys + $actual.keys | select -uniq
foreach ($key in $allKeys) {
if (($actual.keys -contains $key) -and ($expected.keys -contains $key)) {
$history_param = $history + " : hash['$($key)']"
Compare-NonHashes $expected[$key] $actual[$key] $history_param }
elseif ($expected.keys -notcontains $key) {
Write-Host "$($history) : hash['$($key)'] in Actual but not Expected!" }
elseif ($actual.keys -notcontains $key) {
Write-Host "$($history) : hash['$($key)'] in Expected but not Actual!" } } }
function Compare-NonHashes ($expected, $actual, $history='') {
# Helper function for Compare-Hashes.
if ($expected.GetType().Name -eq "HashTable") {
Compare-Hashes $expected $actual $history }
elseif (($expected.GetType().Name -eq "Object[]") -and ($actual.GetType().Name -eq "Object[]"))
{
$maxLength = $($expected.length, $actual.length | Measure -Max).Maximum
for ($i = 0; $i -lt $maxLength; $i++) {
if ($expected[$i] -eq $null) {
Write-Host "$($history) : list['$($actual[$i])'] in Actual but not Expected!" }
elseif ($actual[$i] -eq $null) {
Write-Host "$($history) : list['$($expected[$i])'] in Expected but not Actual!" }
else {
$history_param = $history + " : list[$($i)]"
Compare-NonHashes $expected[$i] $actual[$i] $history_param } } }
else { # String
$different = Compare-Object $expected $actual
if ($different) {
Write-Host "$($history) : <->"
Write-Host " -> Expected '$($expected)'"
Write-Host " -> Actually '$($actual)'" } } }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment