Powershell:过滤 Hashtable - 并取回 Hastable

问题描述 投票:0回答:4

使用 GetEnumerator 过滤哈希表总是返回一个对象 [] 而不是哈希表:

# 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

这个问题有好的解决方案吗?

非常感谢您的帮助! 亲切的问候, 汤姆

powershell hashtable
4个回答
13
投票

$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

5
投票

这是一个更简单的函数,它甚至具有包含和排除功能

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

4
投票

由于接受的答案导致我出现

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($_) 
    }
}

2
投票

在现代

PowerShell
(据我记得
5
+)你可以使用
reduce
模式。为此,您需要使用这种形式的
ForEach-Object

$Hashtable.Keys 
    | ForEach-Object -Begin { 
        $FilteredHashtable = @{} 
    } -Process {
        if ($_ -eq 'Example') {
            $FilteredHashtable[$_] = $Hashtable[$_];
        }
    } -End {
        $FilteredHashtable
    }

是的,这个片段将返回

Hashtable
.

© www.soinside.com 2019 - 2024. All rights reserved.