有没有一种方法可以保留哈希表中键的添加顺序?就像推入/弹出机制一样。
示例:
$hashtable = @{}
$hashtable.Add("Switzerland", "Bern")
$hashtable.Add("Spain", "Madrid")
$hashtable.Add("Italy", "Rome")
$hashtable.Add("Germany", "Berlin")
$hashtable
我希望保留我向哈希表中添加元素的顺序。
有没有一种方法可以保留哈希表中键的添加顺序?就像推入/弹出机制一样。
示例:
$hashtable = @{}
$hashtable.Add("Switzerland", "Bern")
$hashtable.Add("Spain", "Madrid")
$hashtable.Add("Italy", "Rome")
$hashtable.Add("Germany", "Berlin")
$hashtable
我希望保留我向哈希表中添加元素的顺序。
在PowerShell V1 / V2中没有内置的解决方案。您需要使用.NET
System.Collections.Specialized.OrderedDictionary
。
$order = New-Object System.Collections.Specialized.OrderedDictionary
$order.Add("Switzerland", "Bern")
$order.Add("Spain", "Madrid")
$order.Add("Italy", "Rome")
$order.Add("Germany", "Berlin")
PS> $order
Name Value
---- -----
Switzerland Bern
Spain Madrid
Italy Rome
Germany Berlin
在 PowerShell V3 中,您可以将其转换为 [ordered]:
PS> [ordered]@{"Switzerland"="Bern"; "Spain"="Madrid"; "Italy"="Rome"; "Germany"="Berlin"}
Name Value
---- -----
Switzerland Bern
Spain Madrid
Italy Rome
Germany Berlin
$list = New-Object System.Collections.Specialized.OrderedDictionary
$list.Add("Switzerland", "Bern")
$list.Add("Spain", "Madrid")
$list.Add("Italy", "Rome")
$list.Add("Germany", "Berlin")
$list
$hashtable = @{}
$hashtable[$hashtable.count] = @("Switzerland", "Bern")
$hashtable[$hashtable.count] = @("Spain", "Madrid")
$hashtable[$hashtable.count] = @("Italy", "Rome")
$hashtable[$hashtable.count] = @("Germany", "Berlin")
$hashtable
echo "`nHashtable keeping the order as they were added"
foreach($item in $hashtable.getEnumerator() | Sort Key)
{
$item
}
PowerShell 1的方法是添加一个哈希表成员以保留添加顺序。无需使用System.Collections.Specialized.OrderedDictionary:
$Hash = New-Object PSObject
$Hash | Add-Member -MemberType NoteProperty -Name key1 -Value val1
$Hash | Add-Member -MemberType NoteProperty -Name key2 -Value val2
$Hash | Add-Member -MemberType NoteProperty -Name key3 -Value val3
为了与旧版 PowerShell 兼容,您可以考虑使用此 cmdlet:
Function Order-Keys {
param(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)][HashTable]$HashTable,
[Parameter(Mandatory = $false, Position = 1)][ScriptBlock]$Function,
[Switch]$Descending
)
$Keys = $HashTable.Keys | ForEach {$_} # Copy HashTable + KeyCollection
For ($i = 0; $i -lt $Keys.Count - 1; $i++) {
For ($j = $i + 1; $j -lt $Keys.Count; $j++) {
$a = $Keys[$i]
$b = $Keys[$j]
If ($Function -is "ScriptBlock") {
$a = $HashTable[$a] | ForEach $Function
$b = $HashTable[$b] | ForEach $Function
}
If ($Descending) {
$Swap = $a -lt $b
}
Else
{
$Swap = $a -gt $b
}
If ($Swap) {
$Keys[$i], $Keys[$j] = $Keys[$j], $Keys[$i]
}
}
}
Return $Keys
}
$HashTable | Order-Keys | ForEach {Write-Host $_ $HashTable[$_]}
Germany Berlin
Italy Rome
Spain Madrid
Switzerland Bern
$HashTable | Order-Keys {$_} | ForEach {Write-Host $_ $HashTable[$_]}
Germany Berlin
Switzerland Bern
Spain Madrid
Italy Rome
$HashTable = @{
Switzerland = @{Order = 1; Capital = "Berne"}
Germany = @{Order = 2; Capital = "Berlin"}
Spain = @{Order = 3; Capital = "Madrid"}
Italy = @{Order = 4; Capital = "Rome"}
}
$HashTable | Order-Keys {$_.Order} | ForEach {$_}
或按预定义的大写字母排序(降序):
$HashTable | Order-Keys {$_.Capital} -Descending | ForEach {$_}
function sortedKeys([hashtable]$ht) {
$out = @()
foreach($k in $ht.keys) {
$out += $k
}
[Array]::sort($out)
return ,$out
}
和使用它的调用
forEach($k in (& sortedKeys $ht)) {
...
}
function global:sortDictionaryByKey([hashtable]$dictionary)
{
return $dictionary.GetEnumerator() | sort -Property name;
}
[ordered][hash]
快捷方式的变体作为参数类型,并且必须使用完整类型。 您可以将其作为[hash]
参数传递,但是您会失去排序(因为它作为不太具体的扩展hash
类型传递;更多信息请参见该链接),这可能是不可取的。 - ruffin[ordered]
的提示。我在声明全局变量时成功地使用了这个方法:Set-Variable -Name MyOrderedHashtable -Scope global -Option AllScope -Value ([ordered]@{})
。 - MikeOnline