2013-02-15 20 views
21

Utilizzo di Powershell 2.0 C'è un modo per mantenere l'ordine delle chiavi in ​​una tabella hash come sono state aggiunte? Come un meccanismo push/pop.Powershell Hashtables Key Order

Esempio:

$hashtable = @{} 

$hashtable.Add("switzerland","berne") 
$hashtable.Add("germany","berlin") 
$hashtable.Add("spain","madrid") 
$hashtable.Add("italy","rome") 
$hashtable 

voglio mantenere l'ordine in cui ho aggiunto degli elementi alla tabella hash.

risposta

36

non c'è è costruito in soluzione in PowerShell V1/V2, si vuole utilizzare il .NET System.Collections.Specialized.OrderedDictionary

$order = New-Object System.Collections.Specialized.OrderedDictionary 
$order.Add("switzerland","berne") 
$order.Add("germany","berlin") 


PS>$order 

Name       Value 
----       ----- 
switzerland     berne 
germany      berlin 

In PS V3 si può lanciare a [ordinata]:

PS>[ordered]@{"switzerland"="berne";"germany"="berlin"} 

Name       Value 
----       ----- 
switzerland     berne 
germany      berlin 
+0

Grazie per le risposte! Sapevo che PS v3 [ordinato], ma devo usare PS 2.0 – Phil

6

è possibile utilizzare un dizionario ordinato invece: in questo modo:

$list = New-Object System.Collections.Specialized.OrderedDictionary 
$list.Add("switzerland","berne") 
$list.Add("germany","berlin") 
$list.Add("spain","madrid") 
$list.Add("italy","rome") 
$list 
0

Il modo PS1 per aggiungere un membro hashtable mantiene l'ordine di aggiunta. Non è necessario utilizzare 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 
+1

Ma non è un hashtable, è un oggetto PSCustomObject. Non è la stessa cosa, anche se si nomina la variabile "$ Hash". ;) Un OrderedDictionary funziona proprio come un hashtable per tutti gli scopi pratici che ho provato. –

1

Per la compatibilità con le versioni PowerShell più vecchie si potrebbe considerare questo 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 
} 

Questo cmdlet restituisce un elenco di chiave ordinato dal definizione di funzione:

selezionare per nome:

$HashTable | Order-Keys | ForEach {Write-Host $_ $HashTable[$_]} 
germany berlin 
italy rome 
spain madrid 
switzerland berne 

Ordina per valore:

$HashTable | Order-Keys {$_} | ForEach {Write-Host $_ $HashTable[$_]} 
germany berlin 
switzerland berne 
spain madrid 
italy rome 

Si potrebbe anche prendere in considerazione per le tabelle hash nido:

$HashTable = @{ 
    switzerland = @{Order = 1; Capital = "berne"} 
    germany  = @{Order = 2; Capital = "berlin"} 
    spain  = @{Order = 3; Capital = "madrid"} 
    italy  = @{Order = 4; Capital = "rome"} 
} 

Ad es Ordina per (hash) ordine propery e restituire la chiave (paese):

$HashTable | Order-Keys {$_.Order} | ForEach {$_} 

oppure ordinare (decrescente) da predefinito Capitale

$HashTable | Order-Keys {$_.Capital} -Descending | ForEach {$_} 
3

Si può dare una chiave sequenziale quando si aggiungono elementi:

$hashtable = @{} 

$hashtable[$hashtable.count][email protected]("switzerland","berne") 
$hashtable[$hashtable.count][email protected]("germany","berlin") 
$hashtable[$hashtable.count][email protected]("spain","madrid") 
$hashtable[$hashtable.count][email protected]("italy","rome") 
$hashtable 

Quindi, è possibile ottenere gli elementi in ordine di chiave:

echo "`nHashtable keeping the order as they were added" 
foreach($item in $hashtable.getEnumerator() | Sort Key) 
{ 
    $item 
}