PowerShell:过滤Hashtable -并返回一个Hastable

v6ylcynt  于 2023-03-23  发布在  Shell
关注(0)|答案(4)|浏览(127)

使用GetEnumerator过滤Hashtable总是返回一个object[]而不是Hashtable:

# 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

有没有一个很好的解决这个问题的办法?
非常感谢您的帮助!,亲切的问候,汤姆

u7up0aaq

u7up0aaq1#

$filtered是一个字典条目数组。据我所知,没有单类型转换或ctor。
你可以创建一个hash:

$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
4sup72z8

4sup72z82#

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

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}
x一个一个一个一个x一个一个二个一个x一个一个三个一个

x4shl7ld

x4shl7ld3#

由于accepted answer导致了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($_) 
    }
}
odopli94

odopli944#

在一个现代的PowerShell5 +据我所知),你可以使用reduce模式。为此,你需要使用这种形式的ForEach-Object

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

是的,此代码段将返回Hashtable

相关问题