How can I filter a list of objects based on the values of their properties (no matter the property name)

StackOverflow https://stackoverflow.com/questions/22571081

Вопрос

I have a list of objects that look similar to this:

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

Based on the value of each variable passed to the functions, the objects will have different values for Prop1, Prop2, and Prop3. Is there a way to filter the list of objects so I only return objects that have one of their properties set to false? Ex:

$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 }

If I echoed $fails in the pseudo-code above, it would only return $obj2 since it had a false value for one of the properties.

I know it is possible to check every value of each property then manually add them to a new array; but the problem with that is that I have a lot of objects, with a lot of properties (more than I am showing in this example).

Is there any way to filter out the array of objects so that I only get the ones I need?

Это было полезно?

Решение 2

Ok, we're going to add an additional member to your custom objects so that they remember who they are once they're added to the array. Then we'll filter using -match and we'll get what you want.

$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 }

I suppose if you really, really want it to return $obj2 you could escape a $ into the Name value like "Name" ="`$obj2"

Другие советы

Try this:

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

PSObject is a hidden property on all PSObjects, that contains a bunch of information about the object, including being able to iterate through the properties.

This is one possible solution:

$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 } 
    }
}

Or even simpler:

$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 } }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top