【问题标题】:Sort a PowerShell hash table on a property of the value根据值的属性对 PowerShell 哈希表进行排序
【发布时间】:2013-08-02 18:07:10
【问题描述】:

我在对哈希表进行排序时遇到问题。我已将我的代码分解为仅是必需品,以免我的原始脚本让任何人不知所措。

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
}

输出是

PowerShell Version =  3.0
Ascending
2
1
4
3
Descending
2
1
4
3

我确信这只是一个不知道Sort-Object 正确用法的简单案例。排序在Sort-Object Name 上正常工作,所以可能与不知道如何处理Value.SortOrder 有关?

【问题讨论】:

    标签: sorting powershell hashtable


    【解决方案1】:

    Sort-Object 接受用于排序的属性名称或脚本块。由于您尝试对属性的属性进行排序,因此您需要使用脚本块:

    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 }
    

    您可以使用Where-Object cmdlet 进行过滤:

    Write-Host "Ascending"
    $h.GetEnumerator() | 
        Where-Object { $_.Name -ge 2 } |
        Sort-Object { $_.Value.SortOrder } | 
        ForEach-Object {  Write-Host $_.Value.SortOrder }
    

    您通常希望将Where-Object 放在任何Sort-Object cmdlet 之前,因为这样可以加快排序速度。

    【讨论】:

    • 我已经更新了我的问题以使用您提到的代码,但我仍然得到相同的输出。
    • 没关系,看起来我错过了这个时期。我会将问题重新编辑回原来的。
    • 顺便说一句,这可能是一个单独的问题,但有没有简单的方法可以 >= 2 或其他过滤器。
    • 是的,与 Where-Object 的方式非常相似。在 | 之前添加“| Where-Object { $_.Value.SortOrder -ge 2 }”排序对象,不带引号。
    • @ThomasMaierhofer 否。用户不想按Name 属性排序。他想按正在传递的对象的属性上的属性进行排序。
    【解决方案2】:

    我使用哈希表作为频率表来计算文件名中单词的出现次数。

    $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
    

    最后一行发挥了魔力,根据值(频率)对哈希表进行排序。

    【讨论】:

    • 这是一个绝妙的答案。我已经闲逛了几个小时,看到了很多复杂的答案,但这很完美。做得好!我需要在哈希表中进行排序,但是将 $hashtable = {what you write} 放入是一件简单的事情,而且效果很好。非常感谢。
    猜你喜欢
    • 2022-01-21
    • 2012-03-07
    • 1970-01-01
    • 2023-04-01
    • 2015-04-08
    • 1970-01-01
    • 2019-01-29
    • 2021-08-22
    • 1970-01-01
    相关资源
    最近更新 更多