Sort a PowerShell hash table on a property of the value
Solution 1
Sort-Object accepts a property name or a script block used to sort. Since you're trying to sort on a property of a property, you'll need to use a script block:
Write-Host "Ascending"
$h.GetEnumerator() |
Sort-Object { $_.Value.SortOrder } |
ForEach-Object { Write-Host $_.Value.SortOrder }
Write-Host "Descending"
$h.GetEnumerator() |
Sort-Object { $_.Value.SortOrder } -Descending |
ForEach-Object { Write-Host $_.Value.SortOrder }
You can filter using the Where-Object cmdlet:
Write-Host "Ascending"
$h.GetEnumerator() |
Where-Object { $_.Name -ge 2 } |
Sort-Object { $_.Value.SortOrder } |
ForEach-Object { Write-Host $_.Value.SortOrder }
You usually want to put Where-Object
before any Sort-Object
cmdlets, since it makes sorting faster.
Solution 2
I was using a hash table as a frequency table, to count the occurrence of words in filenames.
$words = @{}
get-childitem *.pdf | foreach-object -process {
$name = $_.name.substring($_.name.indexof("-") + 1, $_.name.indexof(".") - $_.name.indexof("-") - 1)
$name = $name.replace("_", " ")
$word = $name.split(" ")[0]
if ( $words.contains($word) ){
$words[$word] = $words[$word] + 1
}else{
$words.add($word, 1)
}
}
$words.getenumerator() | sort-object -property value
It's that last line that does the magic, sorting the hash table on the value(frequency).
Dan P
Updated on February 05, 2020Comments
-
Dan P over 4 years
I'm having an issue sorting a hash table. I've broken down my code to just bare necessities so as not to overwhelm anyone with my original script.
Write-Host "PowerShell Version = " ([string]$psversiontable.psversion) $h = @{} $Value = @{SortOrder=1;v1=1;} $h.Add(1, $Value) $Value = @{SortOrder=2;v1=1;} $h.Add(2, $Value) $Value = @{SortOrder=3;v1=1;} $h.Add(3, $Value) $Value = @{SortOrder=4;v1=1;} $h.Add(4, $Value) Write-Host "Ascending" foreach($f in $h.GetEnumerator() | Sort-Object Value.SortOrder) { Write-Host $f.Value.SortOrder } Write-Host "Descending" foreach($f in $h.GetEnumerator() | Sort-Object Value.SortOrder -descending) { Write-Host $f.Value.SortOrder }
The output is
PowerShell Version = 3.0 Ascending 2 1 4 3 Descending 2 1 4 3
I'm sure this is just a simple case of not knowing the correct usage of
Sort-Object
. The sort works correctly onSort-Object Name
so maybe it has something to do with not knowing how to handle theValue.SortOrder
? -
Dan P almost 11 yearsI've updated my question to use the code you mentioned but I still get the same output.
-
Dan P almost 11 yearsnevermind looks like I missed the period. I'll re edit the question back to the original.
-
Dan P almost 11 yearsbtw this may be separate question but is there easy way to >= 2 or some other filter.
-
Ates Goral almost 11 yearsYes, in very similar fashion with Where-Object. Add "| Where-Object { $_.Value.SortOrder -ge 2 }" before your | Sort-Object, without the quotes.
-
Thomas Maierhofer almost 10 yearsNo need to use a script block. $h.GetEnumerator() | sort Name will do
-
Aaron Jensen almost 10 years@ThomasMaierhofer No. The user doesn't want to sort by a
Name
property. He wants to sort by a property on a property of the object being passed. -
Thomas Maierhofer almost 10 yearsYou're right. Seems that I haven't recognized the whole problem
-
Alan over 6 yearsThat's a brilliant answer. I've been poking around for a couple of hours and seen so many complicated answers, but this works perfect. Well done! I needed the sort in a hash table, but it was a simple matter to put $hashtable = {what you wrote} and it worked great. Thanks so much.