2016-06-04 8 views
10

redakcji: To pytanie ma skomplikowaną historię, ale sprowadza się do tego:
* Aby dowiedzieć się jak do wyliczyć wpisów hashtable przez ich pary klucz-wartość , patrz the accepted answer.
* Aby dowiedzieć się, jak filtr hashtable przez zbiór kluczowych wartości patrz the other answer.
Jak mogę wyliczyć hashtable jako pary klucz-wartość/filtrować hashtable przez zbiór kluczowych wartości


Chyba wpadł problemu X Y ponownie, moje pierwsze pytanie było o Filtrowanie tabeli mieszania. Odkryłem, że łatwiej jest filtrować przed utworzeniem tabeli mieszania. Pytanie odpowiedziało, prawda?

Nie, problem z Y polegał na zapętleniu każdego klawisza i użyciu wartości, które pomogły mi @briantist.

Moim celem jest zapętlenie nazw kluczy, które są sygnaturami czasowymi i zaplanowanie zadania z użyciem nazwy klucza jako nazwy zadania i wyzwalacza.

tworzę tabelę hash z pliku CSV, używając Group-Object -AsHashTable -AsString-Edycja, to warto wspomnieć, że filtrowanie CSV przed utworzeniem Hashtable tylko sprawia, że ​​rzeczy łatwiej dół Pipeline lub skryptu.

Jako przykład:

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

Próbuję pętli nad kluczowych nazwisk i zdolny do wyświetlania nazwy klawiszy przy użyciu:

$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"}} 

ja po prostu nie wiem, jak uzyskać wartości z kluczy, które mnie interesują.

Znalazłem następujące prace, ale tylko wtedy, gdy ręcznie wpisuję Nazwę klawisza. Nie jestem pewien, jak połączyć obie pętle.

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

Aby wyjaśnić, filtrowanie (przynajmniej w PowerShell) jest zawsze najlepiej wykonywane przed lub po lewej stronie operatora Pipeline '|', aby skrypty były wydajniejsze. – user4317867

+2

Rzeczywiście; inaczej mówiąc: używanie natywnego filtrowania przez dostawcę za pomocą parametru "-Filter" (jeśli jest dostępny) jest zwykle znacznie szybsze niż przekazywanie niefiltrowanych danych wyjściowych przez potok, w celu umożliwienia późniejszego wykonania polecenia cmdlet 'Where-Object'. – mklement0

Odpowiedz

17

Masz kilka opcji tutaj.

Wyliczanie za pośrednictwem klawiszy:

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

Wyliczanie par klucz-wartość (co już odkryte, ale nie może być skutecznie używając):

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

Próbowałem kodu w pierwszym bloku, używając instrukcji IF, ponieważ istnieje klucz, który chcę pominąć. Działa to '$ value = $ val [$ key] .server' ale mam dalsze prace filtrowania, które muszą zostać wykonane po tym. Czy może to być tak proste, jak umieszczenie wartości '$ value' w tablicy i filtrowanie po fakcie? – user4317867

+1

@ user4317867 byłoby pomocne, gdybyś był bardziej precyzyjny w tym, co ostatecznie chcesz osiągnąć, ponieważ mogę tylko spekulować na podstawie tego, co powiedziałeś do tej pory. "Dalsze prace filtracyjne" mogą oznaczać wiele rzeczy. – briantist

+0

Przepraszam, poświęciłem pół dnia na to pytanie! Warto wskazać filtr CSV przed utworzeniem hashtable, np. 'Import-CSV file.csv | gdzie {$ _. Column -ne 'String'} ', aby ułatwić sobie pracę! – user4317867

7

celu uzupełnienia briantist's helpful answer poprzez skupienie się na filtrowania hashtable według tablicy kluczowych wartości (PSv3 + składnia):

# 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) } 

celu dalszego przetwarzania pasujących par klucz wartość, po prostu rury do % (ForEach-Object) i dostęp $_.Key i $_.Value (wartości):

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

Z hashtable próbki, to otrzymuje się:

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

Zastosowana powyżej technika filtrowania kluczy to , a nie ograniczenie do filtrowania przez literalnych tablic kluczy; dowolny (string) kolekcja zrobi jak RHS z -in argumencie, takie jak .Keys kolekcji z inny 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)" } 

Rezultat jest taki sam jak w przykładzie z statycznego klucza tablicy.


Nawiasem:

format domyślny wyjście [System.Collections.DictionaryEntry] (a zatem hashtables ([System.Collections.Hashtable]) wykorzystuje nazwa kolumny Name zamiast Key; Name jest zdefiniowana jako właściwość ps z Key dodanej PowerShell (nie jest częścią [System.Collections.DictionaryEntry].NET type definition; weryfikuj za pomocą
).