获得独特的价值

时间:2018-07-27 08:26:01

标签: powershell

我们正在尝试优化一些代码,以尽可能快地从Array中删除重复项。通常,可以通过将输入管道输送到Group-Object然后仅使用Name属性来轻松地完成此操作。但是我们希望避免使用管道,因为它速度较慢。

但是,我们尝试了以下代码:

[System.Collections.ArrayList]$uniqueFrom = @() 

$From = @('A', 'A', 'B')

$From.Where({-not ($uniqueFrom.Contains($_))}).ForEach({
    $uniqueFrom.Add($_)
})

$uniqueFrom

理论上,这应该可行。但是由于某种原因,输出不是预期的@('A', 'B')。为什么不重新评估ArrayList子句中的.where

2 个答案:

答案 0 :(得分:2)

根据我的经验,可以通过使用DataView来减少“管道过滤”以获得唯一值。如果要处理数组,则需要先将其转换为DataTable,然后才能使用DataView获取值。

例如

$arr = @('val1','val1','val1','val2','val1','val3'....)

$newDatatable = New-Object System.Data.Datatable
[void]$newDatatable.Columns.Add("FetchUniqueColumn")

foreach($e in $arr)
{
    $row = $newDatatable.NewRow()
    $row.Item('FetchUniqueColumn') = $e
    $newDatatable.Rows.Add($row)
}

$filterDataView     = New-Object System.Data.Dataview($newDatatable)
$UniqueDT           = $filterDataView.ToTable($true,'FetchUniqueColumn')
$UniqueValues_array = $UniqueDT.Rows.FetchUniqueColumn

请注意,如果您输入的是DataTable,则这样做的速度要快得多,因为在将DataView的唯一值过滤器设置为$true之前,您不必再进行转换。从数据视图创建$UniqueDT数据表:

$UniqueDT = $filterDataView.ToTable($true,'FetchUniqueColumn')

通过从SQL查询具有3000行数据表的1列进行测试。 我的结果如下:

**With 1 column Data Table as input
  Select -Unique - 300 ms 
  Using DataView - 21 ms

**With @() array as input (converted SQL results to array prior to benchmarking)
  Select Unique  - 262 ms
  Using DataView - 106 ms 

答案 1 :(得分:1)


免责声明 :在这个答案中,我只是在解释为什么当前代码无法正常工作,而不是尝试提供其他解决方案。有关解决方案,请检查the accepted answer


  

为什么不重新评估.where子句中的ArrayList?

不应该这样做。它实际上是在这里过滤:

$From.Where({-not ($uniqueFrom.Contains($_))})

然后执行

$uniqueFrom.Add($_)
每个元素的

。和你一样

[System.Collections.ArrayList]$uniqueFrom = @()

此数组为空,因此将为任何$false返回$uniqueFrom.Contains($_)


证明:

要验证我上面写的是正确的,可以执行以下操作:

[System.Collections.ArrayList]$uniqueFrom = @()
$uniqueFrom.add("A")
$From.Where({-not ($uniqueFrom.Contains($_))}).ForEach({
    $uniqueFrom.Add($_)
})

输出为A, B(手动添加了A,跳过了两个A,因为此条目已存在于$uniqueFrom中,B已添加到{{ 1}})。