我正在尝试编写一个过滤掉DataTable中重复条目的函数。我的代码工作正常,但只有行:3-4不在评论中。我尝试将$ tbl1变量的默认范围更改为全局,但它没有帮助。
我在做什么?代码如下。
Function RemoveDuplicates
{
#$tbl1 | export-csv ".\tmp.csv" #Code works perfectly when you uncomment these two lines.
#$tbl1 = import-csv ".\tmp.csv" #
$t_tbl = $tbl1 | Sort-Object -Property Prop3 -Unique
$duplicates = Compare-Object -ReferenceObject $tbl1 -DifferenceObject $t_tbl -Property Prop3
#$duplicates
write-host "tbl1 count: $($tbl1.Rows.Count)"
write-host "t_tbl count: $($t_tbl.Count)"
write-host "duplicates count: $(@($duplicates).Count)"
write-host "Found $($tbl1.Rows.Count) entries. $($t_tbl.Count) entries have unique Prop3. Duplicates: $(@($duplicates).count)"
}
$tbl1 = New-Object System.Data.DataTable
$col1 = New-Object System.Data.DataColumn Prop1,([string])
$col2 = New-Object System.Data.DataColumn Prop2,([string])
$col3 = New-Object System.Data.DataColumn Prop3,([string])
$tbl1.Columns.Add($col1)
$tbl1.Columns.Add($col2)
$tbl1.Columns.Add($col3)
$row = $tbl1.NewRow()
$row.Prop1 = "Jane"
$row.Prop2 = "Doe"
$row.Prop3 = "jane.doe@domain.local"
$tbl1.Rows.Add($row)
$row = $tbl1.NewRow()
$row.Prop1 = "Jack"
$row.Prop2 = "Awesome"
$row.Prop3 = "jane.doe@domain.local"
$tbl1.Rows.Add($row)
$row = $tbl1.NewRow()
$row.Prop1 = "Julia"
$row.Prop2 = "Whatever"
$row.Prop3 = "test@domain.local"
$tbl1.Rows.Add($row)
$row = $tbl1.NewRow()
$row.Prop1 = "Mr"
$row.Prop2 = "ScriptGuy!"
$row.Prop3 = "scriptguy@domain.local"
$tbl1.Rows.Add($row)
$row = $tbl1.NewRow()
$row.Prop1 = "Mrs"
$row.Prop2 = "ScriptLady!"
$row.Prop3 = "scriptlady@domain.local"
$tbl1.Rows.Add($row)
RemoveDuplicates
谢谢
答案 0 :(得分:0)
不幸的是,它与范围无关。它与数据类型有关。
这可能令人沮丧:
Compare-Object采用两个数组并通过它们枚举两者来查找不同的项。作为测试,让我们看看PowerShell如何枚举$tbl1
。 foreach
关键字与对象和数组的参数解析行为非常相似。
foreach($row in $tbl1) { $_ }
输出为空白。这是因为它被视为单个对象,而不是集合。 PowerShell cmdlet参数解析不会枚举默认的集合变量。但是,如果我们通过管道推送表,
$tbl1 | % { $_ }
我们获取每一行的数据:
Prop1 Prop2 Prop3
----- ----- -----
Jane Doe jane.doe@domain.local
Jack Awesome jane.doe@domain.local
Julia Whatever test@domain.local
Mr ScriptGuy! scriptguy@domain.local
Mrs ScriptLady! scriptlady@domain.local
然后,行$t_tbl = $tbl1 | Sort-Object -Property Prop3 -Unique
将创建从Sort对象命令输出的对象数组,事实上,如果我们执行以下操作:$t_tbl.GetType().FullName
; $ tbl | Select-Object -First 1 | %{$ .GetType()。FullName},我们看到它是System.Object[]
(数组),其中每个项目都是System.Data.DataRow
个实例。 $tbl1
但是System.Data.DataTable
实例,而不是数组。
因此,当Compare-Object
完成它的工作时,它正在将数据行数组与单个数据表进行比较。当这些行被注释掉时,请注意$duplicates
的内容。
# Output of Compare-Object -ReferenceObject $tbl1 -DifferenceObject $t_tbl -Property Prop3
Prop3 SideIndicator
----- -------------
jane.doe@domain.local =>
scriptguy@domain.local =>
scriptlady@domain.local =>
test@domain.local =>
<=
参数ReferenceObject
和DifferenceObject
是期待数组。当我们传递DifferenceObject
数组时,我们将ReferenceObject
传递给一个值,cmdlet将其视为大小为1的数组。
DataTable没有Prop3
可供比较。
当你取消注释这些行时,你将CSV文件的内容拉回来,你没有得到一个DataTable对象。您将获得一组System.Management.Automation.PSCustomObject
个实例,其中包含基于CSV文件中的列的成员属性。在这种情况下,Compare-Object现在有两个要比较的数组,两个都有具有Prop3属性的对象。
如果您只需要获取数据表中一列的唯一值,请尝试以下操作:
$tbl1 | Select-Object -ExpandProperty Prop3 | Get-Unique