加速table调整

Accelerate table adjustment

在以下情况下,我需要将三个 CSV 格式的文本文件合并为一个:

pricelist-1.txt中有一个ProductID,它指向table cnet-product- de.txt - 也为 ProductID。 在 cnet-product-de.txt 上,MarketingTextID 指向 table cnet-text-de.txt - 到 ID.

现在我想将这三个文件与一个脚本合并为一个 CSV 文件。 最后,ProductID;描述;制造商零件编号;净价; NetRetailPrice + 文本应从 cnet-text-en.txt.

上传

该脚本有效,但由于双循环和巨大的 txt 文件(最多 300'000 行),它需要永远(超过 8 小时)。 有谁知道如何加速我的脚本?如果您不明白条件,请不要犹豫,因为我不是母语人士。

#start timer
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()

#Declaration
$temp = @()
$merged = @()

#clear existent txt
Clear-Content -Path "C:\temp\ALSO\merged.txt"

#read CSVs
$csvprice = Import-csv -path "C:\temp\ALSO\pricelist-1.txt" -Delimiter ';'
$csvtext = Import-Csv -path "C:\temp\ALSO\cnet-text-de.txt" -Delimiter "`t"  

#Read CSV / Group by MarketingTextID / delete multiple ProductID entries
$PAMID = Import-Csv -path "C:\temp\ALSO\cnet-product-de\cnet-product-de.txt" -Delimiter "`t" |
    Select-Object ProductID, MarketingTextID | 
    Group-Object ProductID | 
    ForEach-Object {
    [PsCustomObject]@{
        ProductID       = $_.group.ProductID | Get-Unique
        MarketingTextID = $_.Group.MarketingTextID -join ','
    }
}

#get a single row from $PAMID
ForEach ($ID1 in $PAMID) {

    #Split the MarketingTextIDs
     = $ID1.MarketingTextID.Split(",")[0]
     = $ID1.MarketingTextID.Split(",")[1]
     = $ID1.MarketingTextID.Split(",")[2]
     = $ID1.MarketingTextID.Split(",")[3]

    #get a single row from $csvtext
    foreach ($ID in $csvtext) {

        #Comparison with the individual MarketingTextIDs and add to $temp variable
        if (($ID.ID -eq ) -Or ($ID.ID -eq ) -Or ($ID.ID -eq ) -Or ($ID.ID -eq )) {
            $temp += $ID1 | Select-Object *, @{name = "Text"; expression = {$ID.Text}}
            break
        }
        else {
            continue
        }

    }
}

#Get a single row from $temp
foreach ($tempid in $temp) {

    #Declaration
    $tid = $tempid.ProductID
    $tmid = $tempid.MarketingTextID
    $ttext = $tempid.Text

    #Get a single row from $csvprice
    foreach ($Price in $csvprice) {

        #Comparison ProductIDs and add to $merged Variable
        if ($Price.ProductID -eq $tid) {
            $Price = $Price | select *, @{name = "MarketingTextID"; expression = {$tmid}}
            $Price = $Price | select *, @{name = "Text"; expression = {$ttext}}
            $merged += $Price
            break
        }
        else {
            continue
        }
    }

}
#Export to txt in UTF8 format
$merged | Export-Csv -Path "C:\temp\Also\merged.txt" -Encoding UTF8

#Exit and output timer
$stopwatch.stop()
Write-Host "The script took $($stopwatch.elapsed.totalminutes) minutes"

如果您需要交叉连接 300000 行 CSV,那么您正在查看内循环的 300 亿次 次迭代。即使每个花费的时间都不到一毫秒,你也会看到几个小时:就像你一样。

您需要减少迭代次数。目前你正在循环结束时做一个 continue ......你只寻找第一个结果。所以内部循环只得到一个值,因此:

foreach ($ID in $csvtext){
  if(($ID.ID -eq ) -Or ($ID.ID -eq ) -Or ($ID.ID -eq ) -Or ($ID.ID -eq )) {
    $temp += $ID1 | select *,@{name="Text";expression={$ID.Text}}
    break
  } else { 
     continue
  }
}

可以变成:

$opts = , , , ;
$innerRes = $csvtext | Where-Object $_.ID -in $opts |
             select-object -first 1 |
             select-object *,@{name="Text";expression={$_.Text}}

外循环上的类似转换意味着您可以将管道分配给结果而不是附加到数组(前者比后者更快)。

通常:使用平台的核心范例(在 PowerShell 中:管道)通常比使用其他系列的范例更好。

最后:这可能是您的工具错误的情况:将每个 CSV 上传到数据库并使用 SQL(专为此类操作而设计),但您需要使用SQL 中的设置操作不是命令式代码。