如何根据属性值过滤对象列表(无论属性名称)

时间:2014-03-21 23:07:27

标签: select powershell filter filtering powershell-v2.0

我有一个与此类似的对象列表:

$srvobj = New-Object PSObject -Property @{
    "Prop1" = Do-Something $value
    "Prop2" = Do-SomethingElse $othervalue
    "Prop3" = Do-AnotherThing $thirdvalue
}

根据传递给函数的每个变量的值,对象将具有Prop1,Prop2和Prop3的不同值。有没有办法过滤对象列表,所以我只返回其属性设置为false的对象?例如:

$obj1 = New-Object PSObject -Property @{
    "Prop1" = $true
    "Prop2" = $true
    "Prop3" = $true
}

$obj2 = New-Object PSObject -Property @{
    "Prop1" = $true
    "Prop2" = $false
    "Prop3" = $true
}

$objarray = @($obj1, $obj2)

$fails = $objarray | Where-Object { $_ -contains $false }

如果我在上面的伪代码中回显了$fails,它只会返回$obj2,因为它对其中一个属性有一个假值。

我知道可以检查每个属性的每个值,然后手动将它们添加到新数组中;但问题是我有很多对象,有很多属性(比我在这个例子中显示的更多)。

有没有办法过滤掉对象数组,以便我只得到我需要的那些?

3 个答案:

答案 0 :(得分:2)

试试这个:

$fails = $objArray | % { 
    $obj = $_
    $obj.PSObject.Properties | % { 
        if ($_.Value -eq $false) {
            $obj
        }
    }
}

PSObject是所有PSObject上的隐藏属性,它包含有关该对象的大量信息,包括能够遍历属性。

答案 1 :(得分:0)

好的,我们将在您的自定义对象中添加一个额外的成员,以便他们记住一旦将它们添加到数组中,他们就是谁。然后我们将使用-match进行过滤,我们会得到您想要的内容。

$obj1 = New-Object PSObject -Property @{
    "Name" = "Obj1"
    "Prop1" = $true
    "Prop2" = $true
    "Prop3" = $true
}

$obj2 = New-Object PSObject -Property @{
    "Name" = "Obj2"
    "Prop1" = $true
    "Prop2" = $false
    "Prop3" = $true
}

$objarray = @($obj1, $obj2)

$fails = $objarray | Where-Object { $_ -match $false }

我想如果您确实希望它返回$obj2,您可以将$转换为名称值,例如"Name" =`$obj2"

答案 2 :(得分:0)

这是一种可能的解决方案:

$obj1 = New-Object PSObject -Property @{
    "Prop1" = $true
    "Prop2" = $true
    "Prop3" = $true
}

$obj2 = New-Object PSObject -Property @{
    "Prop1" = $true
    "Prop2" = $false
    "Prop3" = $true
}

$objarray = @($obj1, $obj2)

$objarray | Where-Object { 
    $obj = $_
    $obj | gm -MemberType Properties | % { 
        if($obj."$($_.Name)" -eq $false) { $true } 
    }
}

甚至更简单:

$obj1 = New-Object PSObject -Property @{
    "Prop1" = $true
    "Prop2" = $true
    "Prop3" = $true
}

$obj2 = New-Object PSObject -Property @{
    "Prop1" = $true
    "Prop2" = $false
    "Prop3" = $true
}

$objarray = @($obj1, $obj2)

$objarray | ? { $_.psobject.Properties | ? { $_.Value -eq $false } }