根据值的属性对 PowerShell 哈希表进行排序

Posted

技术标签:

【中文标题】根据值的属性对 PowerShell 哈希表进行排序【英文标题】:Sort a PowerShell hash table on a property of the value 【发布时间】: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 有关?

【问题讨论】:

【参考方案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 放入是一件简单的事情,而且效果很好。非常感谢。

以上是关于根据值的属性对 PowerShell 哈希表进行排序的主要内容,如果未能解决你的问题,请参考以下文章

PowerShell对象排序(结合哈希表)

插入带位置的有序哈希表

Powershell 排序哈希表

在 Powershell 中输出数组的哈希表

PowerShell:组合两个哈希表

PowerCLI脚本,利用哈希表对参数进行转换