I have hit a wall trying to get a hash table of hash tables to sort. It seems like the act of sorting is turning the hash table into something else, and I am unable to walk the new structure.
$mainHashTable = @{}
$mainHashTable.Add('B', @{'one'='B1'; 'two'='B2'; 'three'='B3'})
$mainHashTable.Add('D', @{'one'='D1'; 'two'='D2'; 'three'='D3'})
$mainHashTable.Add('A', @{'one'='A1'; 'two'='A2'; 'three'='A3'})
$mainHashTable.Add('C', @{'one'='C1'; 'two'='C2'; 'three'='C3'})
CLS
$mainHashTable
foreach ($hashtable in $mainHashTable.keys) {
foreach ($itemKey in $mainHashTable.$hashtable.keys) {
Write-Host "$itemKey $($mainHashTable.$hashtable.$itemKey)!"
}
}
Write-Host
$sortedHashTable = $mainHashTable.GetEnumerator() | sort-object -property name
$sortedHashTable
foreach ($hashtable_S in $sortedHashTable.keys) {
foreach ($itemKey_S in $sortedHashTable.$hashtable_S.keys) {
Write-Host "$itemKey_S $($sortedHashTable.$hashtable_S.$itemKey2)!"
}
}
The two lines that dump $mainHashTable
& $sortedHashTable
to the console look like everything is fine. But the second loop set does nothing. I have tried casting like this
$sortedHashTable = [hashtable]($mainHashTable.GetEnumerator() | sort-object -property name)
and that just throws the error
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Collections.Hashtable".
So, is there some way to convert the system object to a hash table, so the loop structure works on the sorted results? Or am I better off learning to walk the structure of the System.Object? And (academically perhaps), is there a way to sort a hash table and get back a hash table?
What you're currently doing is splitting the hashtable into a list of separate entries (via .GetEnumerator()
) and then sorting that - so you end up with $sortedHashTable
being just an array of key
/value
pair objects, sorted by key, not an actual [hashtable]
.
is there a way to sort a hash table and get back a hash table?
No - you can't "sort a hash table" inline, because hashtables do not retain any guaranteed key order.
The way to go here is to copy the entries to an ordered dictionary, in order:
$sortedHashTable = [ordered]@{}
# Sort the keys, then insert into our ordered dictionary
foreach($key in $mainHashTable.Keys |Sort-Object){
$sortedHashTable[$key] = $mainHashTable[$key]
}