Gor*_*don 2 sorting powershell hashtable
我在排序的哈希表中看到一些看似非常奇怪的行为,然后尝试查看结果。我构建了哈希表,然后我需要根据值对该表进行排序,我看到了两个奇怪的地方。
这在课堂外工作正常
$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
Run Code Online (Sandbox Code Playgroud)
我看到散列的内容两次,未排序然后排序。然而,当使用一个类时它什么也不做。
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()
Run Code Online (Sandbox Code Playgroud)
这只是将 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)!!"
}
Run Code Online (Sandbox Code Playgroud)
但是,非常奇怪的是,这仅显示了第一个基于循环的输出,但同时显示了直接转储。
$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
Run Code Online (Sandbox Code Playgroud)
现在的输出是
conformset 3!
applyset 1!
Name Value
---- -----
conformset 3
applyset 1
applyset 1
conformset 3
Run Code Online (Sandbox Code Playgroud)
所以显然 $hash 正在被排序。但是循环不会显示它?嗯?这是错误的行为,还是我不明白其原因的预期行为,以及解决方法?
Vasil Svilenov Nikolov 的有用回答解释了您的方法的基本问题:
从根本上讲,您无法[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提供了这个功能(还有一个通用版本,正如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++
Run Code Online (Sandbox Code Playgroud)
或者甚至从(和到)现有的哈希表转换:
# 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
Run Code Online (Sandbox Code Playgroud)
[1] 请注意,这与 PowerShell 使用文字语法提供的有序字典不同[ordered] @{ ... }:有序字典按照键的插入顺序维护键,而不是基于排序。有序字典的类型System.Collections.Specialized.OrderedDictionary
| 归档时间: |
|
| 查看次数: |
1687 次 |
| 最近记录: |