Powershell 排序哈希表
Posted
技术标签:
【中文标题】Powershell 排序哈希表【英文标题】:Powershell sorting hash table 【发布时间】:2020-04-17 07:05:15 【问题描述】:我看到我正在排序的哈希表出现一些看似非常奇怪的行为,然后尝试查看结果。我构建了哈希表,然后我需要根据值对该表进行排序,我看到了两个奇怪的地方。
这在课堂之外也能正常工作
$hash = [hashtable]::New()
$type = 'conformset'
$hash.Add($type, 1)
$type = 'applyset'
$hash.Add($type , 1)
$type = 'conformset'
$hash.$type ++
$hash.$type ++
$hash
Write-Host
$hash = $hash.GetEnumerator() | Sort-Object -property:Value
$hash
我看到哈希的内容两次,未排序,然后排序。 然而,当使用一个类时,它什么也不做。
class Test
# Constructor (abstract class)
Test ()
$hash = [hashtable]::New()
$type = 'conformset'
$hash.Add($type, 1)
$type = 'applyset'
$hash.Add($type , 1)
$type = 'conformset'
$hash.$type ++
$hash.$type ++
$hash
Write-Host
$hash = $hash.GetEnumerator() | Sort-Object -property:Value
$hash
[Test]::New()
这只是将 Test 回显到控制台,与哈希表无关。我在这里的假设是,它与管道如何被中断有关,老实说,考虑到污染管道错误的常见程度,这是转移到类的一个很好的理由。因此,转向基于循环的方法,这将无法显示类中的第二个已排序、已排序的哈希表。
$hash = [hashtable]::New()
$type = 'conformset'
$hash.Add($type, 1)
$type = 'applyset'
$hash.Add($type , 1)
$type = 'conformset'
$hash.$type ++
$hash.$type ++
foreach ($key in $hash.Keys)
Write-Host "$key $($hash.$key)!"
Write-Host
$hash = ($hash.GetEnumerator() | Sort-Object -property:Value)
foreach ($key in $hash.Keys)
Write-Host "$key $($hash.$key)!!"
但是,非常奇怪的是,这仅显示了第一个基于循环的输出,但同时显示了两个直接转储。
$hash = [hashtable]::New()
$type = 'conformset'
$hash.Add($type, 1)
$type = 'applyset'
$hash.Add($type , 1)
$type = 'conformset'
$hash.$type ++
$hash.$type ++
foreach ($key in $hash.Keys)
Write-Host "$key $($hash.$key)!"
$hash
Write-Host
$hash = ($hash.GetEnumerator() | Sort-Object -property:Value)
foreach ($key in $hash.Keys)
Write-Host "$key $($hash.$key)!!"
$hash
现在的输出是
conformset 3!
applyset 1!
Name Value
---- -----
conformset 3
applyset 1
applyset 1
conformset 3
显然 $hash 正在排序。但是循环不会显示它?嗯?这是错误的行为,还是我只是不明白原因的预期行为,以及解决方法?
【问题讨论】:
哈希表类型不可排序。 [grin] 如果你想要一个排序的字典,使用 >>>SortedList<TKey,TValue> Class (System.Collections.Generic) | Microsoft Docs — https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.sortedlist-2?view=netframework-4.8
【参考方案1】:
Vasil Svilenov Nikolov's helpful answer 解释了您的方法的根本问题:
您根本无法通过键对哈希表进行排序([hashtable]
实例):无法保证哈希表中键的顺序也无法更改。
$hash = $hash.GetEnumerator() | Sort-Object -property:Value
所做的是创建一个 [System.Collections.DictionaryEntry]
实例的数组;结果数组没有.Keys
属性,因此永远不会进入第二个foreach ($key in $hash.Keys)
循环。
一个不相关的问题是您通常无法隐式从 PowerShell 类写入输出流:
从类方法写入输出流需要显式使用return
;同样,必须通过Throw
语句报告错误。
在您的情况下,代码位于类 Test
的 构造函数 中,构造函数隐式返回新构造的实例 - 您不允许 return
来自它们的任何内容。李>
为了解决您的问题,您需要一种专门的数据类型,它结合了哈希表的功能并以排序顺序维护条目键。[1 ]
.NET 类型System.Collections.SortedList
提供此功能(还有一个generic version,如Lee Dailey 注释):
您可以使用该类型开头:
# Create a SortedList instance, which will maintain
# the keys in sorted order, as entries are being added.
$sortedHash = [System.Collections.SortedList]::new()
$type = 'conformset'
$sortedHash.Add($type, 1) # Or: $sortedHash[$type] = 1 or: $sortedHash.$type = 1
$type = 'applyset'
$sortedHash.Add($type , 1)
$type = 'conformset'
$sortedHash.$type++
$sortedHash.$type++
甚至从现有的哈希表转换(和转换为):
# Construct the hash table as before...
$hash = [hashtable]::new() # Or: $hash = @
$type = 'conformset'
$hash.Add($type, 1)
$type = 'applyset'
$hash.Add($type , 1)
$type = 'conformset'
$hash.$type++
$hash.$type++
# ... and then convert it to a SortedList instance with sorted keys.
$hash = [System.Collections.SortedList] $hash
[1] 请注意,这与 ordered 字典不同,后者是 PowerShell 以文字语法 [ordered] @ ...
提供的:有序字典按照它们的顺序维护键 插入,而不是基于排序。有序字典的类型为System.Collections.Specialized.OrderedDictionary
【讨论】:
【参考方案2】:当您执行 $hash = $hash.GetEnumerator() | Sort-Object -property:Value
时,您正在将哈希表重新分配给数组,请尝试 $hash.GetType()
,这当然与哈希表的行为不同,您可以查看方法等。Get-Member -InputObject $hash
我不认为您可以对哈希表进行排序,而且您也不需要。你可以试试 Ordered Dictionary $hash = [Ordered]@
有序字典与哈希表的不同之处在于键总是 按照您列出它们的顺序出现。 a中键的顺序 哈希表未确定。
我喜欢哈希表的最佳用途之一是搜索速度。
例如,可以通过以下方式立即获取哈希表中某个名称的值$hash['applyset']
如果您想了解更多关于哈希表的工作原理,以及如何/何时使用它,我认为这篇文章是一个好的开始: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_hash_tables?view=powershell-6
【讨论】:
良好的诊断,但请注意 ordered 哈希表 - 插入顺序 被维护 - 与 键为排序。 OP想要后者。以上是关于Powershell 排序哈希表的主要内容,如果未能解决你的问题,请参考以下文章