【发布时间】:2017-12-01 10:07:57
【问题描述】:
在以下情况下,我需要将三个 CSV 格式的文本文件合并为一个:
在 pricelist-1.txt 中有一个 ProductID,它指向表 cnet-product-de.txt - 也指向 ProductID。
在 cnet-product-de.txt 上,MarketingTextID 指向表 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
$1 = $ID1.MarketingTextID.Split(",")[0]
$2 = $ID1.MarketingTextID.Split(",")[1]
$3 = $ID1.MarketingTextID.Split(",")[2]
$4 = $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 $1) -Or ($ID.ID -eq $2) -Or ($ID.ID -eq $3) -Or ($ID.ID -eq $3)) {
$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"
【问题讨论】:
-
你应该看看
Join-Objectcmdlet 和-contains运算符,我认为... -
我同意 Join-Object 可能是要走的路。您尝试做的类似于关系连接,这是 SQL 非常擅长的事情。大多数数据库系统都包含一个优化器,它会找出一个相当有效的策略,一个可能涉及在主内存中创建索引信息的策略。您的算法看起来像是蛮力。当你有这么多数据时,你就不能那样做。
标签: performance powershell foreach import-from-csv