Powershell:过滤 Hashtable - 并取回 Hastable
Powershell: Filter Hashtable - and get back a Hastable
始终使用 GetEnumerator 过滤哈希表 returns 一个对象[] 而不是哈希表:
# Init Hashtable
$items = @{ a1 = 1; a2 = 2; b1 = 3; b2 = 4}
# apply a filter
$filtered = $items.GetEnumerator() | ?{ $_.Key -match "a.*" }
# The result looks great
$filtered
Name Value
---- -----
a2 2
a1 1
# … but it is not a Hashtable :-(
$filtered.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
这个问题有好的解决办法吗?
非常感谢您的帮助!,
亲切的问候,
汤姆
$filtered
是一个字典条目数组。据我所知,没有单一演员表或演员。
不过你可以构造一个散列:
$hash = @{}
$filtered | ForEach-Object { $hash.Add($_.Key, $_.Value) }
另一个工作流程:
# Init Hashtable
$items = @{ a1 = 1; a2 = 2; b1 = 3; b2 = 4}
# Copy keys to an array to avoid enumerating them directly on the hashtable
$keys = @($items.Keys)
# Remove elements not matching the expected pattern
$keys | ForEach-Object {
if ($_ -notmatch "a.*") {
$items.Remove($_)
}
}
# $items is filtered
由于 导致我出现 BadEnumeration
异常(但仍然有效),我将其修改为不引发异常并确保原始 HashTable
不通过先克隆修改:
# Init Hashtable
$items = @{ a1 = 1; a2 = 2; b1 = 3; b2 = 4}
$filtered = $items.Clone()
$items.Keys | ForEach-Object {
if ($_ -notmatch "a.*") {
$filtered.Remove($_)
}
}
在现代 PowerShell
(据我记得是 5
+)上,您可以使用 reduce
模式。为此,您需要使用这种形式的 ForEach-Object
:
$Hashtable.Keys | ForEach-Object {$FilteredHashtable = @{}} {
if ($_ -eq 'Example') {
$FilteredHashtable[$_] = $Hashtable[$_];
}
} {$FilteredHashtable}
是的,此代码段将 return Hashtable
。
这是一个更简单的函数,它甚至具有包含和排除功能
function Select-HashTable {
[CmdletBinding()]
param (
[Parameter(Mandatory,ValueFromPipeline)][Hashtable]$Hashtable,
[String[]]$Include = ($HashTable.Keys),
[String[]]$Exclude
)
if (-not $Include) {$Include = $HashTable.Keys}
$filteredHashTable = @{}
$HashTable.keys.where{
$PSItem -in $Include
}.where{
$PSItem -notin $Exclude
}.foreach{
$filteredHashTable[$PSItem] = $HashTable[$PSItem]
}
return $FilteredHashTable
}
示例:
$testHashtable = @{a=1;b=2;c=3;d=4}
$testHashTable | Select-HashTable -Include a
Name Value
---- -----
a 1
$testHashTable | Select-HashTable -Exclude b
Name Value
---- -----
c 3
d 4
a 1
$testHashTable | Select-HashTable -Include a,b,c -Exclude b
Name Value
---- -----
a 1
c 3
始终使用 GetEnumerator 过滤哈希表 returns 一个对象[] 而不是哈希表:
# Init Hashtable
$items = @{ a1 = 1; a2 = 2; b1 = 3; b2 = 4}
# apply a filter
$filtered = $items.GetEnumerator() | ?{ $_.Key -match "a.*" }
# The result looks great
$filtered
Name Value
---- -----
a2 2
a1 1
# … but it is not a Hashtable :-(
$filtered.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
这个问题有好的解决办法吗?
非常感谢您的帮助!, 亲切的问候, 汤姆
$filtered
是一个字典条目数组。据我所知,没有单一演员表或演员。
不过你可以构造一个散列:
$hash = @{}
$filtered | ForEach-Object { $hash.Add($_.Key, $_.Value) }
另一个工作流程:
# Init Hashtable
$items = @{ a1 = 1; a2 = 2; b1 = 3; b2 = 4}
# Copy keys to an array to avoid enumerating them directly on the hashtable
$keys = @($items.Keys)
# Remove elements not matching the expected pattern
$keys | ForEach-Object {
if ($_ -notmatch "a.*") {
$items.Remove($_)
}
}
# $items is filtered
由于 BadEnumeration
异常(但仍然有效),我将其修改为不引发异常并确保原始 HashTable
不通过先克隆修改:
# Init Hashtable
$items = @{ a1 = 1; a2 = 2; b1 = 3; b2 = 4}
$filtered = $items.Clone()
$items.Keys | ForEach-Object {
if ($_ -notmatch "a.*") {
$filtered.Remove($_)
}
}
在现代 PowerShell
(据我记得是 5
+)上,您可以使用 reduce
模式。为此,您需要使用这种形式的 ForEach-Object
:
$Hashtable.Keys | ForEach-Object {$FilteredHashtable = @{}} {
if ($_ -eq 'Example') {
$FilteredHashtable[$_] = $Hashtable[$_];
}
} {$FilteredHashtable}
是的,此代码段将 return Hashtable
。
这是一个更简单的函数,它甚至具有包含和排除功能
function Select-HashTable {
[CmdletBinding()]
param (
[Parameter(Mandatory,ValueFromPipeline)][Hashtable]$Hashtable,
[String[]]$Include = ($HashTable.Keys),
[String[]]$Exclude
)
if (-not $Include) {$Include = $HashTable.Keys}
$filteredHashTable = @{}
$HashTable.keys.where{
$PSItem -in $Include
}.where{
$PSItem -notin $Exclude
}.foreach{
$filteredHashTable[$PSItem] = $HashTable[$PSItem]
}
return $FilteredHashTable
}
示例:
$testHashtable = @{a=1;b=2;c=3;d=4}
$testHashTable | Select-HashTable -Include a
Name Value
---- -----
a 1
$testHashTable | Select-HashTable -Exclude b
Name Value
---- -----
c 3
d 4
a 1
$testHashTable | Select-HashTable -Include a,b,c -Exclude b
Name Value
---- -----
a 1
c 3