在 Powershell 中按键匹配两个大型对象数组的最快方法

Rob*_*rto 1 powershell

我有两个通过 Import-CSV 生成的 powershell 对象数组,我必须通过它们的属性之一来匹配它们。具体来说,这是一种 1:n 关系,因此目前我遵循以下模式:

foreach ($line in $array1) {
    $match=$array2 | where {$_.key -eq $line.key} # could be 1 or n results
    ...# process here the 1 to n lines
}
Run Code Online (Sandbox Code Playgroud)

,这不是很有效(两个表都有很多列)并且花费的时间对于我们的需求来说是不可接受的。有没有最快的方法来执行这场比赛?

两个数据源都来自 csv 文件,因此也欢迎使用某些内容代替 Import-CSV。谢谢

wOx*_*xOm 5

标准方法是使用哈希表(或其他语言中的字典/映射)对数据进行索引。

function buildIndex($csv, [string]$keyName) {
    $index = @{}
    foreach ($row in $csv) {
        $key = $row.($keyName)
        $data = $index[$key]
        if ($data -is [Collections.ArrayList]) {
            $data.add($row) >$null
        } elseif ($data) {
            $index[$key] = [Collections.ArrayList]@($data, $row)
        } else {
            $index[$key] = $row
        }
    }
    $index
}
Run Code Online (Sandbox Code Playgroud)

$csv1 = Import-Csv 'r:\1.csv'
$csv2 = Import-Csv 'r:\2.csv'

$index2 = buildIndex $csv2, 'key'

foreach ($row in $csv1) {
    $matchedInCsv2 = $index2[$row.key]
    foreach ($row2 in $matchedInCsv2) {
        # ........
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,如果您需要速度并迭代一个大集合,请避免|流水线,因为它比 foreach/while/do语句慢很多倍。并且不要像where {$_.key -eq $line.key}代码中那样使用带有 ScriptBlock 的任何内容,因为与内部的简单代码相比,执行上下文创建会增加非常大的开销。