我遇到了一个问题,当存在布尔值时,我无法根据嵌套对象的值有效地过滤对象。
拿下面的物品,我想找出哪个物品是笔记本电脑。
id name fields
-- ---- ------
1 device1 {@{id=1; label=ip address; value=192.168.0.1}, @{id=2; label=type; value=Computer}, @{id=3; label=active; value=True}}
2 device2 {@{id=4; label=ip address; value=192.168.0.2}, @{id=5; label=type; value=Laptop}, @{id=6; label=active; value=True}}
通常我会使用where-object
$laptop = $devices | where-object {$_.fields.value -eq "Laptop"}
不幸的是返回both设备。我花了一段时间才弄清楚原因,但这是因为“活动”字段对象中的 $true 值。
好的。所以我尝试进一步过滤它:
$laptop = $devices | where-object {$_.fields.value -eq "Laptop" -and $_.fields.label -eq "type"}
那根本没用。同样的结果。返回在某处具有“真”值的每个对象。
所以我尝试了这个,这让我得到了正确的字段值:
$laptop = $devices | select-object -expandproperty fields | where-object {$_.label -eq "type" -and $_.value -eq "laptop"}
这对我没有帮助,因为我需要知道顶级对象。更具体地说,顶部对象的 id 值。
我了解到我可以保留原始对象的属性并仍然过滤:
$laptop = $devices | select-object -property id -expandproperty fields | where-object {$_.label -eq "type -and $_.value -eq "laptop"}
上面抛出这个错误是因为属性“id”也存在于子对象中:
select-object : 无法处理该属性,因为属性“id”已经存在。
我最终能够通过逐层使用可笑的嵌套 foreach 语句来实现我的目标,但这一直让我的大脑流血,而且在规模上看起来效率低得可怕。
从
fields
创建新对象,这将使过滤更容易:
$deviceRecords = $devices |ForEach-Object {
# copy the id and name property values to a new ordered dictionary
$properties = [ordered]@{
id = $_.id
name = $_.name
}
# copy each of the field values to the dictionary
$_.fields |Sort-Object id |ForEach-Object {
$properties[$_.label] = $_.value
}
# output a new output with the properties described in the dictionary
[pscustomobject]$properties
}
现在找到笔记本电脑所需要做的就是:
$deviceRecords |Where-Object type -eq Laptop
# or
$deviceRecords |Where-Object {$_.type -eq 'Laptop' -and $_.active}