首页 > 解决方案 > 在powershell中,如何在一个数组中测试已经包含一个具有所有相同属性的对象?

问题描述

我想避免将重复项插入到 powershell 中的数组中。尝试使用-notcontains似乎不适用于PSCUstomObject数组。

这是一个代码示例

$x = [PSCustomObject]@{
    foo = 111
    bar = 222
}

$y = [PSCustomObject]@{
    foo = 111
    bar = 222
}

$collection = @()

$collection += $x

if ($collection -notcontains $y){
    $collection += $y
}


$collection.Count #Expecting to only get 1, getting 2

标签: powershellpscustomobject

解决方案


我会为此使用比较对象

$x = [PSCustomObject]@{
    foo = 111
    bar = 222
}

$y = [PSCustomObject]@{
    foo = 111
    bar = 222
}
$collection = [System.Collections.Arraylist]@()

[void]$collection.Add($x)

if (Compare-Object -Ref $collection -Dif $y -Property foo,bar | Where SideIndicator -eq '=>') {
    [void]$collection.Add($y)
}

解释:

使用比较运算符将自定义对象与另一个对象进行比较并非易事。此解决方案比较您关心的特定属性(foobar这种情况下)。这可以简单地使用 来完成Compare-Object,默认情况下将输出任一对象的差异。的SideIndicator=>表示不同之处在于传入-Difference参数的对象。

[System.Collections.Arraylist]类型用于数组,以避免+=在增长数组时通常出现的低效。由于该.Add()方法生成正在修改的索引的输出,因此[void]使用强制转换来抑制该输出。


您可以对有关属性的解决方案进行动态处理。您可能不想将属性名称硬编码到Compare-Object命令中。您可以改为执行以下操作。

$x = [PSCustomObject]@{
    foo = 111
    bar = 222
}

$y = [PSCustomObject]@{
    foo = 111
    bar = 222
}
$collection = [System.Collections.Arraylist]@()

[void]$collection.Add($x)
$properties = $collection[0] | Get-Member -MemberType NoteProperty |
                  Select-Object -Expand Name

if (Compare-Object -Ref $collection -Dif $y -Property $properties | Where SideIndicator -eq '=>') {
    [void]$collection.Add($y)
}

推荐阅读