在组内过滤 - 组 - 对象

时间:2018-03-23 21:31:31

标签: powershell

背景信息:
每个元素的IndicatorType为“' 10'或者' ND'
指标的值为“'!' ,'' (空字符串/ null),' o',' u'

问题:
我需要过滤每个"元素"中的数据。基于此伪代码规则的组,然后将结果导出到文件:
For Each" Element"分组如果指标='!'或者''对于BOTH IndicatorTypes(即' 10',' ND'),选择指示符类型= ND的组 ELSE如果指标='!'或者''对于IndicatorType = 10和指标=' o'或者' u' for IndicatorType = ND选择indicatorType = 10

的组

我的源文件:

"Code","IndicatorType","Indicator","Element","Data"
"111","10","","S","0.039"
"111","10","!","Cr ","0.045"
"111","10","","Zn","0.011"
"111","10","!","P","0.013"
"111","10","","Ni ","56.480"
"111","10","!","Co ","1.081"
"111","10","!","Fe","45.655"
"111","10","!","Si","0.364"
"111","10","!","Mn","0.005"
"111","10","!","Al","0.007"
"111","10","!","Cu","0.014"
"111","10","!","Y","0.00"
"111","ND","","S","0.037"
"111","ND","","Cr ","0.039"
"111","ND","","Zn","0.010"
"111","ND","","P","0.013"
"111","ND","o","Ni ","37.107"
"111","ND","o","Co ","0.887"
"111","ND","o","Fe","37.430"
"111","ND","","Si","0.348"
"111","ND","","Mn","0.005"
"111","ND","","Al","0.008"
"111","ND","","Cu","0.013"
"111","ND","","Y","0.00"

按元素分组我的代码:

$myfile = Get-ChildItem -Path $myfileSource *.csv
$myfileData = Import-Csv $myfile.FullName | Group-Object Element | 
              Where-Object -FilterScript {($_.Group.IndicatorType -eq 'ND' -and
                                          $_.Group.Indicator -eq '!' -or 
                                          $_.Group.Indicator -eq '') -or
                                          ($_.Group.IndicatorType -eq '10' -and
                                          $_.Group.Indicator -eq 'o' -or 
                                          $_.Group.Indicator -eq 'u' -or 
                                          $_.Group.Indicator -eq '!' -or
                                          $_.Group.Indicator -eq '')  
                                         }| Export-Csv -Path $myFile.FullName -Force -NoTypeInformation

PROBEM:
问题在于我的Where-Object,它返回所有值。
如何将伪代码规则应用于Where-Object以仅选择所需的组? enter image description here

2 个答案:

答案 0 :(得分:2)

$_.Group将返回同一元素的两个对象,因此您的测试将使用-eq右侧的值过滤列表(例如,组中两个对象的IndicatorType),并且条件很可能是真的。例如:

$_.Group.IndicatorType -eq 'ND'
#Translates to array of "IndicatorTypes in the group" -eq 'ND'
10,'ND' -eq 'ND'
#The line above filters the array on the left to show matching values, this returns
'ND'
#A value is always true, so this test will be
$true

您可以通过首先在要执行测试的组中查找对象来解决此问题。

此外,使用Group-Object Element | Where-Object …意味着如果where子句为true,则将保留从Group-Object返回的整个对象(包含Count,Name和elements-group)。您应该使用Foreach-Object,因为您只想为每个已批准的元素组保留一个对象。尝试:

$myfile = Get-ChildItem -Path $myfileSource *.csv

$myfileData = Import-Csv $myfile.FullName | 
#For Each "Element" Group
Group-Object Element | Foreach-Object {
    $Ten = $_.Group | Where-Object { $_.IndicatorType -eq '10' }
    $ND = $_.Group | Where-Object { $_.IndicatorType -eq 'ND' }

    if(('!','' -contains $Ten.Indicator) -and ('!','' -contains $ND.Indicator)) {
        #if Indicator='!' or '' for BOTH IndicatorTypes(ie '10','ND'), Select group where indicatorType=ND
        $ND
    } elseif (('!','' -contains $Ten.Indicator) -and ('o','u' -contains $ND.Indicator)) {
        #ELSE if Indicator='!' or '' for IndicatorType = 10 and Indicator='o' or 'u' for IndicatorType=ND Select group where indicatorType=10
        $Ten
    }
} | Export-Csv -Path $myFile.FullName -Force -NoTypeInformation

答案 1 :(得分:0)

Group-Object返回GroupInfo个对象的集合,每个对象都包含组中元素的集合 - 基本上是列表列表。运行cmdlet会生成(基于示例输入)12个组的列表:

PS[1] (191) > $data = import-csv  data2.txt | group-object element
PS[1] (192) > $data.Count
12

查看返回的第一项:

PS[1] > $data[0].Group.Count
2

您可以看到它包含两个看起来像这样的条目:

PS[1] (193) > $data[0].Group

Code          : 111
IndicatorType : 10
Indicator     :
Element       : S
Data          : 0.039

Code          : 111
IndicatorType : ND
Indicator     :
Element       : S
Data          : 0.037

这意味着您的选择条件必须应用于与该组关联的数据集合中的每个/所有条目,以决定是否要返回该组。在您的示例代码中,您似乎假设某个群体是平的而不是。但遗憾的是,我并不完全理解您要尝试的内容,因此我无法提供完整的答案。