【问题标题】:Powershell 5, Is there an easy way to compare property values from array of hashtablesPowershell 5,是否有一种简单的方法来比较哈希表数组中的属性值
【发布时间】:2021-10-17 08:49:44
【问题描述】:

我正在尝试找到一种方法来比较 2 个哈希表数组,以查看某些属性是否匹配。

如果有匹配,我需要某个值发生,如果没有匹配,则需要执行其他操作。

理论上嵌套循环应该可以完成这项工作,但我必须弄清楚哪个数组更长。

代码示例如下:

$hashtable1 = @{}
$hashtable1.name = "xxx"
$hashtable1.surname =@()
$hashtable1.surname += "bbb"

$hashtable2 = @{}
$hashtable2.name = "aaa"
$hashtable2.surname =@()
$hashtable2.surname += "ccc"

$hashtable3 = @{}
$hashtable3.name = "bbb"
$hashtable3.surname = @()
$hashtable3.surname += "xxx"

$A = @($hashtable1; $hashtable2; $hashtable3)

$hashtable4 = @{}
$hashtable4.name = "yyy"
$hashtable4.surname =@()
$hashtable4.surname += "bbb"

$hashtable5 = @{}
$hashtable5.name = "xxx"
$hashtable5.surname = @()
$hashtable5.surname += "ccc"

$hashtable6 = @{}
$hashtable6.name = "ddd"
$hashtable6.surname = @()
$hashtable6.surname += "xxx"

$hashtable7 = @{}
$hashtable7.name = "ddd"
$hashtable7.surname = @()
$hashtable7.surname += "xxx"

$Array1 = @($hashtable1; $hashtable2; $hashtable3)
$Array2 = @($hashtable4; $hashtable5; $hashtable6; $hashtable7)

在这种情况下,我需要找出:hashtable1.name 与 hashtable5.name 相同,然后采取某些措施。

我想知道是否有更好的方法。

请注意,我昨天在这里问了一个类似的问题:

Powershell Compare 2 Arrays of Hashtables based on a property value

该解决方案适用于稍微不同的场景,但这次,我真的需要将数组中的哈希表参数相互比较。

我在 Windows 10 上使用 PowerShell 5。

谢谢, 紫菀

【问题讨论】:

    标签: arrays powershell nested iteration hashtable


    【解决方案1】:

    你可以测试一下:

    $commonNames = (Compare-Object $Array1.name $Array2.name -IncludeEqual -ExcludeDifferent).inputObject
    

    【讨论】:

    • 就个人而言,我会在Compare-Object 之前使用任何其他方法,除非我要比较两个基元数组。这是一个 比看起来更愚蠢的命令。
    【解决方案2】:

    除了JPBlanc's helpful answer。我认为返回匹配的对象可能很有用。如果展开 name 属性,则只会返回 name 属性。幸运的是 Compare-Object 有一些参数可以帮助解决这个问题。特别是:

    -Property :指示Compare-Object 要比较底层对象上的哪个属性。

    -PassThru :返回带有添加属性“SideIndicator”的原始对象,此时您仍然可以确定哪些对象具有等效名称属性。

    这可能最终看起来像:

    Compare-Object $Array1 $Array2 -Property Name -PassThru -IncludeEqual | 
    Where-Object{ $_.SideIndicator -eq '==' }
    

    但是:

    这不会很好地过滤,因为 HashTables 是根据定义集合名称/值对,因此当 PowerShell 展开数组以进行比较时,它将尝试过滤名称/值对中的名称列/属性,这不是你要。取而代之的是,您要过滤的名称键的值是由“名称”引用的,非常混乱。您可以通过将哈希表正式转换为对象来解决此问题,而 PowerShell 使这变得非常容易:

    $Array1 = @([PSCustomObject]$hashtable1; [PSCustomObject]$hashtable2; [PSCustomObject]$hashtable3)
    $Array2 = @([PSCustomObject]$hashtable4; [PSCustomObject]$hashtable5; [PSCustomObject]$hashtable6; [PSCustomObject]$hashtable7)
    
    Compare-Object $Array1 $Array2 -Property Name -PassThru -IncludeEqual | 
    Where-Object{ $_.SideIndicator -eq '==' }
    

    现在如果合适的话,你可以清理一下:

    $Object1 = [PSCustomObject]@{
        $Object1.name    = "xxx"
        $Object1.surname = @("bbb")
    }
    
    $Object2 = [PSCustomObject]@{
        $Object2.name    = "aaa"
        $Object2.surname = @("ccc")
    }
    
    $Object3 = [PSCustomObject]@{
        $Object3.name    = "bbb"
        $Object3.surname =  @("xxx")
    }
    
    $Object4 = [PSCustomObject]@{
        $Object4.name    = "yyy"
        $Object4.surname = @("bbb")
    }
    
    $Object5 = [PSCustomObject]@{
        $Object5.name    = "xxx"
        $Object5.surname =  @("ccc")
    }
    
    $Object6 = [PSCustomObject]@{
        $Object6.name    = "ddd"
        $Object6.surname =  @("xxx")
    }
    
    $Object7 = [PSCustomObject]@{
        $Object7.name    = "ddd"
        $Object7.surname =  @("xxx")
    }
    
    $Array1 = @($Object1; $Object2; $Object3)
    $Array2 = @($Object4; $Object5; $Object6; $Object7)
    
    Compare-Object $Array1 $Array2 -Property Name -PassThru -IncludeEqual | 
    Where-Object{ $_.SideIndicator -eq '==' }
    

    上面的例子只是说你可以从对象开始,像以前一样,可以通过简单地将哈希表转换为[PSCustomObject]来创建对象。但是,在这种情况下,是转换 Hash 文字而不是变量。请注意,您不需要使用+= 来附加姓氏值。

    注意:我意识到您提供的哈希表可能是一个简单的演示结构。如果输入真的来自其他地方,我们可能需要稍微不同的编码才能在概念上遵循相同的模式。

    【讨论】:

      【解决方案3】:

      您还可以在匹配时返回哈希表本身,而不是像这样返回 .name 属性:

      Compare-Object $Array1 $Array2 -IncludeEqual -ExcludeDifferent -Property @{Expression = {$_['name']}} -PassThru
      

      -Property参数的值可以是一个新的计算属性。
      通过使用-PassThru 参数,Compare-Object 省略了比较对象周围的 PSCustomObject 包装器并返回不同或相等的对象,保持不变。

      结果:

      Name                           Value                                                                                                                                     
      ----                           -----                                                                                                                                     
      name                           xxx                                                                                                                                       
      surname                        {bbb}
      

      附:创建可以简化使用的数组

      $Array1 = $hashtable1, $hashtable2, $hashtable3
      $Array2 = $hashtable4, $hashtable5, $hashtable6, $hashtable7
      

      所以你不需要@()

      【讨论】:

        猜你喜欢
        • 2021-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-11
        • 2012-06-15
        • 1970-01-01
        • 2019-01-02
        • 1970-01-01
        相关资源
        最近更新 更多