Using Sort-Object on array of hash tables Using Sort-Object on array of hash tables powershell powershell

Using Sort-Object on array of hash tables


Sort-Object a is not working because a isn't a property, it's a key in a hashtable. One might be confused because PowerShell hides this for you by accepting $ht.a even though it actually uses $ht["a"] behind the scenes, but if you run $array | Get-Member you can confirm that the property a doesn't exist.

A workaround is to sort by using calculated properties that access the keys in the hashtable. I used Select-Object to show the hashtables in a table so it's easier to see the results. Ex:

$array = @()$array += @{a = 7; b = 2}$array += @{a = 3; b = 4}$array += @{a = 3; b = 1}$array += @{a = 5; b = 9}$array += @{a = 1; b = 5}#No sort$array | Select-Object @{n="a";e={$_.a}}, @{n="b";e={$_.b}}a b- -7 23 43 15 91 5#Sort by a asc, then b asc$array | Sort-Object { $_.a },  { $_.b } | Select-Object @{n="a";e={$_.a}}, @{n="b";e={$_.b}}a b- -1 53 13 45 97 2


See answer by @Frode F. for a detailed explanation, but that answer does miss one situation. When the outer container only has one item (i.e. when the array only contains one hashtable), Sort-Object "conveniently" sorts the inner container.

So...Where $array.Count -eq 1, the elements of that hashtable are sorted.Where $array.Count -gt 1, the elements of the array are sorted.

As a workaround, use:

if ($array.Count -gt 1) {    $result = Sort-Object { $_.a }, {$_.b }} else {    $result = $array}