Как я могу перечислить хэш-таблицу в качестве пар ключ-значение/фильтровать хеш-таблицу по набору ключевых значений

Примечание редактора: Этот вопрос имеет сложную историю, но сводится к следующему:
* Чтобы узнать, как перечислить записи хэш-таблицы по ее парам ключ-значение, см. принятый ответ.
* Чтобы узнать, как фильтровать хэш-таблицу с помощью набора ключевых значений, см. другой ответ.


Я думаю, что снова попал в проблему X Y, мой первоначальный вопрос касался фильтрации хэш-таблицы. Я обнаружил, что проще фильтровать до создания хеш-таблицы. Ответ на вопрос, верно?

Нет, проблема Y заключалась в циклизации каждого ключа и использовании значений, которые мне помог @briantist.

Моя цель - перебрать имена ключей, которые являются отметками времени, и запланировать задачу с использованием имени ключа в качестве имени задачи и триггера.

Я создаю хэш-таблицу из файла CSV с помощью Group-Object -AsHashTable -AsString -edit, стоит упомянуть здесь, что фильтрация CSV до создания HashTable упрощает работу с Pipeline или script.

В качестве примера:

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

Я пытаюсь перебрать имена ключей и отобразить имена ключей, используя:

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

Я просто не уверен, как получить значения из интересующих меня ключей.

Я нашел следующие работы, но только когда я вводил имя ключа вручную. Я просто не знаю, как объединить оба цикла.

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

Ответ 1

У вас есть несколько вариантов.

Перечисление через клавиши:

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

Перечисление пар ключ-значение (которое вы обнаружили, но не можете эффективно использовать):

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

Ответ 2

Чтобы дополнить бриантистский полезный ответ, сосредоточив внимание на фильтрации хэш-таблицы массивом ключевых значений (синтаксис 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) }

Для дальнейшей обработки пар пар ключ-значение просто подключитесь к % (ForEach-Object) и получите доступ к $_.Key и $_.Value (значение):

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

С образцом хеш-таблицы это дает:

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

Используемая выше технология фильтрации ключей не ограничивается фильтрацией массивами буквенных ключей; любая (строка) коллекция будет выполнять как RHS операнда -in, например, в коллекции .Keys другой хеш-таблицы:

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

Результат такой же, как в примере с массивом статических ключей.


В стороне:

Формат вывода по умолчанию для [System.Collections.DictionaryEntry] (и, следовательно, hashtables ([System.Collections.Hashtable]) использует имя столбца Name, а не Key; Name определяется как свойство псевдонима Key, добавленное PowerShell (it не является частью [System.Collections.DictionaryEntry] Определение типа .NET, проверьте с помощью @{ one = 1 }.GetEnumerator() | Get-Member).