2016-06-04 29 views
10

Nota del redattore: Questa domanda ha una storia complicata, ma si riduce a questo:
* Per imparare come elencare le voci di una tabella hash dalle sue coppie di valori-chiave , vedere the accepted answer.
* per imparare a filtro una tabella hash da una collezione di valori chiave, vedere the other answer.
Come posso elencare una tabella hash come coppie chiave-valore/filtrare una tabella hash da un insieme di valori chiave


penso Sono caduto nella problema X Y di nuovo, la mia domanda iniziale era su come filtrare una tabella hash. Ho scoperto che è più facile filtrare prima di creare la tabella hash. Domanda risposta, giusto?

No, il problema Y era il looping di ogni chiave e l'utilizzo dei valori con cui @briantist mi ha aiutato.

Il mio obiettivo è eseguire il looping dei nomi delle chiavi, che sono timestamp, e pianificare un'attività utilizzando il nome della chiave come nome dell'attività e trigger.

Sto creando una tabella di hash da un file CSV utilizzando Group-Object -AsHashTable -AsString-edit, vale la pena ricordare qui che il filtraggio del CSV prima di creare il HashTable fa solo le cose più facili lungo il Pipeline o lo script.

Per fare un esempio:

Import-CSV (ls -path D:\ -Filter source*.csv | sort LastWriteTime | Select -Last 1).FullName | 
where {$_.TimeCorrected -ne 'ManualRebootServer'} | 
group TimeCorrected -AsHashTable -AsString 

Sto cercando di ciclo sui nomi chiave e in grado di visualizzare i nomi dei tasti utilizzando:

$var = Import-Csv csv123.csv | Group-Object Value1 -AsHashTable -AsString 

foreach ($key in $var.Keys){"The key name is $key"} 

#Create a scheduled task named and triggered based on the HashTable keyname 
#test test test 
foreach ($key in $var.keys){IF($key -ne 'ManualRebootServer'){"Register-ScheduledJob"}} 

io non sono solo sicuro di come ottenere i valori delle chiavi che mi interessano.

Ho trovato i seguenti lavori, ma solo quando inserisco manualmente il nome di una chiave. Sono solo sicuro di come combinare entrambi i loop.

($val.GetEnumerator() | Where {$_.key -eq '06-11-16 18:00'} | ForEach-Object { $_.value }).Server 
+0

Solo per offrire una spiegazione, il filtraggio (almeno in PowerShell) viene sempre eseguito prima o alla sinistra dell'operatore Pipeline '|' per rendere gli script più efficienti. – user4317867

+2

Infatti; per dirla in modo diverso: l'utilizzo del filtro nativo del provider con il parametro '-Filter' (se disponibile) è in genere molto più rapido del passaggio dell'output non filtrato attraverso la pipeline per consentire al cmdlet' Where-Object' di eseguire il filtro in un secondo momento. – mklement0

risposta

17

Avete alcune opzioni qui.

enumerazione tramite i tasti:

foreach ($key in $var.Keys) { 
    $value = $var[$key] 
    # or 
    $value = $var.$key 
} 

enumerazione coppie chiave-valore (che hai scoperto, ma non può essere un efficace utilizzo):

foreach ($kvp in $var.GetEnumerator()) { 
    $key = $kvp.Key 
    $val = $kvp.Value 
} 
+0

Ho provato il codice nel primo blocco, usando un'istruzione IF perché c'è una chiave che voglio saltare. Questo funziona '$ valore = $ val [$ chiave] .server', ma ho bisogno di ulteriore lavoro di filtraggio che deve essere fatto dopo questo. Potrebbe essere semplice come mettere il valore $ in una matrice e filtrare dopo il fatto? – user4317867

+1

@ user4317867 sarebbe di grande aiuto se tu fossi più esplicito in ciò che stai cercando di ottenere, in quanto posso solo speculare sulla base di ciò che hai detto finora. "Ulteriori lavori di filtraggio" possono significare molte cose. – briantist

+0

Mi scuso, ho messo una mezza giornata in questa domanda! Vale la pena sottolineare che è necessario filtrare il CSV prima di creare l'hashtable, ad esempio "Import-CSV file.csv | dove {$ _. Column -ne 'String'} 'per semplificare le cose! – user4317867

7

Per completare briantist's helpful answer concentrandosi su filtraggio un hash di una serie di valori chiave (sintassi PSv3 +):

# Sample hashtable. 
$ht = @{ one = 1; two = 2; three = 3 } 

# Filter it by an array of key values; applying .GetEnumerator() yields an array 
# of [System.Collections.DictionaryEntry] instances, which have 
# a .Key property and a .Value property. 
$ht.GetEnumerator() | ? Key -in 'one', 'two' 

# Similarly, the *output* - even though it *looks* like a hashtable - 
# is a regular PS *array* ([Object[]]) containing [System.Collections.DictionaryEntry] 
# entries (2 in this case). 
$arrFilteredEntries = $ht.GetEnumerator() | ? Key -in 'one', 'two' 
$arrFilteredEntries.GetType().Name # -> Object[] 

# Use the following technique to reassemble the filtered entries into 
# a single output hashtable: 
$htFiltered = @{} 
$ht.GetEnumerator() | ? Key -in 'one', 'two' | % { $htFiltered.Add($_.Key, $_.Value) } 

Per elaborare ulteriormente le corrispondenti coppie di valori-chiave, semplicemente tubo % (ForEach-Object) e accesso $_.Key e $_.Value (valore):

$ht.GetEnumerator() | ? Key -in 'one', 'two' | 
    % { "Value for key '$($_.Key)': $($_.Value)" } 

Con la tabella hash di esempio, questo produce:

Value for key 'one': 1 
Value for key 'two': 2 

La tecnica di filtraggio dei tasti utilizzata in precedenza è non limitata al filtro tramite gli array di chiavi letterali; qualsiasi (stringa) di raccolta farà come RHS del -in operando, ad esempio la raccolta di un .Keysdiversa hashtable:

# Sample input hashtable. 
$htInput = @{ one = 1; two = 2; three = 3 } 

# Hashtable by whose keys the input hashtable should be filtered. 
# Note that the entries' *values* are irrelevant here. 
$htFilterKeys = @{ one = $null; two = $null } 

# Perform filtering. 
$htInput.GetEnumerator() | ? Key -in $htFilterKeys.Keys | 
    % { "Value for key '$($_.Key)': $($_.Value)" } 

Il risultato è lo stesso come nell'esempio con l'array chiave statica.


Per inciso:

Il formato di output predefinito per [System.Collections.DictionaryEntry] (e quindi hashtables ([System.Collections.Hashtable]) utilizza nome della colonna Name anziché Key; Name è definita come una proprietà alias di Key aggiunti dai PowerShell (non fa parte di [System.Collections.DictionaryEntry].NET type definition; verifica con
@{ one = 1 }.GetEnumerator() | Get-Member).

Problemi correlati