我需要帮助来调试我创建的以下示例代码,以模拟一个真实的场景,在该场景中,根据嵌套的pscustomobject属性与$filterTags中存储的值的区分大小写匹配来过滤$objects pscustomobject数组。
# Filtering on the following strings. ***Must match case***
$filterTags = @("application","environment")
$objects = @(
[PSCustomObject]@{ Name = "Object1"; tags = [PSCustomObject]@{ "Application" = "App1"; Environment = "Env1" }},
[PSCustomObject]@{ Name = "Object2"; tags = [PSCustomObject]@{ "Application" = "App2"; environment = "Env2" }},
[PSCustomObject]@{ Name = "Object3"; tags = [PSCustomObject]@{ "application" = "App3"; Environment = "Env3" }},
[PSCustomObject]@{ Name = "Object4"; tags = [PSCustomObject]@{ "Migrate Project" = "Migration1"}}
)
$objects | Where-Object {
$tagsNames = $_.tags.PSObject.Properties.Name
$filterTags | ForEach-Object { $tagsNames -ceq $_ }
}
Name tags
---- ----
Object2 @{Application=App2; environment=Env2}
Object3 @{application=App3; Environment=Env3}
Object4 @{Migrate Project=Migration1}
我只期望对象2和3由最后一个语句返回。对象1和对象4不匹配,所以对象1被过滤掉是很好的,但为什么对象4会出现呢?
当我运行下面的代码时,我得到了预期的False值,因为它是唯一一个不匹配的标记,所以我不明白为什么它会出现在上面的代码中。
# variable set from previous code final loop
$tagsNames
Migrate Project
$myTags | ForEach-Object { $tagsNames -ceq $_ }
False
False
我尝试了以下方法,使用了ccontains,它忽略了对象4,但返回对象1、2和3。
$objects | Where-Object {
$_.tags.PSObject.Properties.Name | % {$myTags -ccontains $_ }
}
Tia
2条答案
按热度按时间k5ifujac1#
答案是因为一个包含多个元素的集合强制为
$true
,不管它们的元素是什么。参见从集合类型转换:$true
。您的筛选条件应该使用
Where-Object
或.Where
,而不是ForEach-Object
。在这种情况下,.Where
更好,因为它具有First
模式,它更有效,因为它的行为类似于Enumerable.Any
。h6my8fg22#
有趣的是,我找到了一个使用cmatch的解决方案。