如何将哈希表枚举为键值对/通过键值集合过滤哈希表
How can I enumerate a hashtable as key-value pairs / filter a hashtable by a collection of key values
编者注:
这个问题来历很复杂,归结为:
* 了解如何通过键值对[=47]枚举散列table的条目=],参见 。
* 了解如何通过键值集合 过滤散列table,参见 。
我想我又陷入了 X Y 问题,我最初的问题是关于过滤哈希 table。我发现在创建散列 table 之前进行过滤更容易。问题回答对了吗?
不,Y 问题是循环每个键并使用@briantist 帮助我的值。
我的目标是遍历作为时间戳的键名,并使用键名作为任务名称和触发器来安排任务。
我正在使用 Group-Object -AsHashTable -AsString
-edit 从 CSV 文件创建哈希 [=56=],这里值得一提的是,在创建哈希表之前过滤 CSV 只会让事情变得更容易向下 Pipeline
或脚本 。
举个例子:
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
这里有一些选项。
通过键枚举:
foreach ($key in $var.Keys) {
$value = $var[$key]
# or
$value = $var.$key
}
枚举键值对(您已经发现,但可能未有效使用):
foreach ($kvp in $var.GetEnumerator()) {
$key = $kvp.Key
$val = $kvp.Value
}
通过专注于通过键值数组过滤哈希表来补充 (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[]
要进一步 处理匹配的键值对 ,只需通过管道传输到 %
(ForEach-Object
) 并访问 $_.Key
和 $_.Value
(值):
$ht.GetEnumerator() | ? Key -in 'one', 'two' |
% { "Value for key '$($_.Key)': $($_.Value)" }
等效命令使用更高效的foreach
循环而不是管道:
foreach ($key in $ht.Keys) {
if ($key -in 'one', 'two') { "Value for key '$($key)': $($ht.$key)" }
}
注:在PSv2中:
* 不支持运算符 -in
,但您可以使用 -contains
代替操作数 swapped:
'one', 'two' -contains $key
* 在管道中,使用 Where-Object { 'one', 'two' -contains $_.Key }
使用示例哈希表,这会产生:
Value for key 'two': 2
Value for key 'one': 1
请注意输出中的键顺序与定义顺序有何不同;在 PSv3+ 中,您可以创建 ordered 哈希表 ([ordered] @{ ... }
) 以保留定义顺序。
上面使用的key-filtering技术not仅限于literalkey数组过滤;任何(字符串)集合都将作为 -in
操作数的 RHS,例如 different 哈希表的 .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)" }
# `foreach` loop equivalent:
foreach ($key in $htInput.Keys) {
if ($key -in $htFilterKeys.Keys) { "Value for key '$($key)': $($htInput.$key)" }
}
结果与使用静态筛选键数组的示例中的结果相同。
最后,如果您想 过滤哈希表 就地 或 创建一个 新的 仅包含过滤条目的哈希表:
# *In-place* Updating of the hashtable.
# Remove entries other than the ones matching the specified keys.
# Note: The @(...) around $ht.Keys is needed to clone the keys collection before
# enumeration, so that you don't get an error about modifying a collection
# while it is being enumerated.
foreach ($key in @($ht.Keys)) {
if ($key -notin 'one', 'two') { $ht.Remove($key) }
}
# Create a *new* hashtable with only the filtered entries.
# By accessing the original's .Keys collection, the need for @(...) is obviated.
$htNew = $ht.Clone()
foreach ($key in $ht.Keys) {
if ($key -notin 'one', 'two') { $htNew.Remove($key) }
}
顺便说一句:
[System.Collections.DictionaryEntry]
(因此哈希表 ([System.Collections.Hashtable]
) 的默认输出格式使用列名 Name
而不是 Key
;Name
定义为由 PowerShell 添加的 Key
的 别名 属性(它不是 [System.Collections.DictionaryEntry]
.NET type definition 的一部分;验证与
@{ one = 1 }.GetEnumerator() | Get-Member
).
编者注:
这个问题来历很复杂,归结为:
* 了解如何通过键值对[=47]枚举散列table的条目=],参见
* 了解如何通过键值集合
我想我又陷入了 X Y 问题,我最初的问题是关于过滤哈希 table。我发现在创建散列 table 之前进行过滤更容易。问题回答对了吗?
不,Y 问题是循环每个键并使用@briantist 帮助我的值。
我的目标是遍历作为时间戳的键名,并使用键名作为任务名称和触发器来安排任务。
我正在使用 Group-Object -AsHashTable -AsString
-edit 从 CSV 文件创建哈希 [=56=],这里值得一提的是,在创建哈希表之前过滤 CSV 只会让事情变得更容易向下 Pipeline
或脚本 。
举个例子:
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
这里有一些选项。
通过键枚举:
foreach ($key in $var.Keys) {
$value = $var[$key]
# or
$value = $var.$key
}
枚举键值对(您已经发现,但可能未有效使用):
foreach ($kvp in $var.GetEnumerator()) {
$key = $kvp.Key
$val = $kvp.Value
}
通过专注于通过键值数组过滤哈希表来补充
# 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[]
要进一步 处理匹配的键值对 ,只需通过管道传输到 %
(ForEach-Object
) 并访问 $_.Key
和 $_.Value
(值):
$ht.GetEnumerator() | ? Key -in 'one', 'two' |
% { "Value for key '$($_.Key)': $($_.Value)" }
等效命令使用更高效的foreach
循环而不是管道:
foreach ($key in $ht.Keys) {
if ($key -in 'one', 'two') { "Value for key '$($key)': $($ht.$key)" }
}
注:在PSv2中:
* 不支持运算符 -in
,但您可以使用 -contains
代替操作数 swapped:
'one', 'two' -contains $key
* 在管道中,使用 Where-Object { 'one', 'two' -contains $_.Key }
使用示例哈希表,这会产生:
Value for key 'two': 2
Value for key 'one': 1
请注意输出中的键顺序与定义顺序有何不同;在 PSv3+ 中,您可以创建 ordered 哈希表 ([ordered] @{ ... }
) 以保留定义顺序。
上面使用的key-filtering技术not仅限于literalkey数组过滤;任何(字符串)集合都将作为 -in
操作数的 RHS,例如 different 哈希表的 .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)" }
# `foreach` loop equivalent:
foreach ($key in $htInput.Keys) {
if ($key -in $htFilterKeys.Keys) { "Value for key '$($key)': $($htInput.$key)" }
}
结果与使用静态筛选键数组的示例中的结果相同。
最后,如果您想 过滤哈希表 就地 或 创建一个 新的 仅包含过滤条目的哈希表:
# *In-place* Updating of the hashtable.
# Remove entries other than the ones matching the specified keys.
# Note: The @(...) around $ht.Keys is needed to clone the keys collection before
# enumeration, so that you don't get an error about modifying a collection
# while it is being enumerated.
foreach ($key in @($ht.Keys)) {
if ($key -notin 'one', 'two') { $ht.Remove($key) }
}
# Create a *new* hashtable with only the filtered entries.
# By accessing the original's .Keys collection, the need for @(...) is obviated.
$htNew = $ht.Clone()
foreach ($key in $ht.Keys) {
if ($key -notin 'one', 'two') { $htNew.Remove($key) }
}
顺便说一句:
[System.Collections.DictionaryEntry]
(因此哈希表 ([System.Collections.Hashtable]
) 的默认输出格式使用列名 Name
而不是 Key
;Name
定义为由 PowerShell 添加的 Key
的 别名 属性(它不是 [System.Collections.DictionaryEntry]
.NET type definition 的一部分;验证与
@{ one = 1 }.GetEnumerator() | Get-Member
).