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