【问题标题】:Powershell: Filter Hashtable - and get back a HastablePowershell:过滤 Hashtable - 并取回 Hastable
【发布时间】:2016-06-17 10:20:40
【问题描述】:

使用 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

这个问题有什么好的解决办法吗?

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

【问题讨论】:

    标签: powershell hashtable


    【解决方案1】:

    $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
    

    【讨论】:

    • 您好,briantist,非常感谢您非常快速而完整的回答!我不敢相信没有单一的演员或演员,但你可能是对的。至少,解决方法是透明且可用的:-)
    • 您可能希望将 $items.Keys 替换为 @($items.Keys),以便在从中删除项目时不枚举集合。
    • 您需要使用@()$()。普通括号不能解决问题。
    • @PetSerAl 或者我可以更清楚一点,只需使用单独的变量:-p
    • 您仍然需要使用$keys = @($items.Keys)@($keys) | ForEach-Object ...。在开始枚举之前,您需要制作集合的副本。分配给变量不要复制。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      在现代PowerShell(据我所知5+)上,您可以使用reduce 模式。为此,您需要使用ForEach-Object 的这种形式:

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

      是的,这个 sn-p 将返回 Hashtable

      【讨论】:

        【解决方案4】:

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

        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
        

        【讨论】:

          猜你喜欢
          • 2016-06-13
          • 1970-01-01
          • 2018-11-24
          • 1970-01-01
          • 2021-01-16
          • 1970-01-01
          • 1970-01-01
          • 2012-01-15
          • 2013-06-13
          相关资源
          最近更新 更多