我需要有关在CSV文件上进行PowerShell编程的帮助。
我进行了一些搜索,但找不到所需的内容(或者也许我不知道技术术语)。基本上,我有一个Excel工作簿,其中包含大量数据(或多或少38列x 350.000行),并且有两个公式需要几个小时才能计算出来。
我首先想知道,与Excel相比,PowerShell是否可以加快计算速度。实际上,占用我大部分时间的计算并不那么复杂(至少乍一看)。我的数据大致是这样构造的:
Ref Title ----- -------------------------- A/001 "free_text" A/002 "free_text A/001 free_text" ... ... A/005 "free_text A/004 free_text" A/006 "free_text" B/001 "free_text" B/002 "free_text" C/001 "free_text" C/002 "free_text" ... C/050 "free_text C/047 free_text" ... ... C/103 "free_text" D/001 "free_text" D/002 "free_text D/001 free_text" ... ....
基本数据如下:
{letter}/{incremental value}
格式的唯一值。但是,我100%确信以下几点:
{letter}
块。例如:标题字段中的字符串'C / 047'只能在 Ref {letter}
为C的块中找到。在标题中调用的 Ref 将始终位于 Ref 的“之后”(或较低行)中。它指的是。换句话说,我不能使用以下格式的行:
Ref Title ------------ ----------------------------------------- {letter/i} {free_text {letter/j} free_text} with j<i
→这是不可能的。
→j总是> i
我已在Excel中使用这些特征来最大程度地减少查找数组。但是计算一切仍然需要一个小时。
因此,我研究了PowerShell,并开始使用CSV进行“播放”,并使用ForEach-Object
循环播放,希望得到更快的结果。到目前为止,我基本上在CSV文件上循环了两次。
$CSV1 = myfile.csv
$CSV2 = myfile.csv
$CSV1 | ForEach-Object {
# find Title
$TitSearch = $_.$Ref
$CSV2 | ForEach-Object {
if ($_.$Title -eq $TitSearch) {
myinstructions
}
}
}
它有效,但是真的很长。因此,我尝试了以下方法,而不是使用$CSV2 | ForEach...
:
$CSV | where {$_.$Title -eq $TitleSearch} | % $Ref
在任何一种情况下,它都太长且根本没有效率。此外,对于这两种解决方案,我没有使用上述特征,因为它们可能会减少查找数组,并且如上所述,看来我最终在CSV文件中从头到尾循环了两次。
问题:
{letter}
块创建1个文件(A块1个文件,B 1个文件等等)。但是我有大约50.000块要创建。或一个一个地创建它们,进行分析,将结果放入一个新文件中,然后删除它们。这样会更快吗?
注意:这是工作,供其他同事使用,Excel和PowerShell实际上是我们可能会使用的唯一软件。我知道VBA,但还可以...最后,我很好奇如何以及是否可以使用PowerShell以简单的方式解决此问题。
答案 0 :(得分:0)
据我所知,您的基本算法进行了N ^ 2迭代(约1,200亿)。有一种提高效率的标准方法-您需要先构建一个哈希表。 Hashtable是键/值存储,并且查找几乎是瞬时的,因此算法的时间复杂度将变为〜N。 Powershell为此提供了内置数据类型。在您的情况下,键将是ref,其值是单元格数据数组(假设您的表像是ref,title,col1,...,colN一样)
$hash = @{}
foreach($row in $table} {$hash.Add($row.ref, @($row.title, $row.col1, ...)}
#it will take 350K steps to generate it
#then you can iterate over it again
foreach($key in $hash.Keys) {
$key # access current ref
$rowData = $hash.$key # access to current row elements (by index)
$refRowData = $hash[$rowData[$j]] # lookup from other rows, assuming lookup reference is in some column
}
因此,解决时间问题是一个普遍的想法。老实说,我不认为您需要重新创建轮子并自己编写代码。您需要一个关系数据库。既然您具有Excel,那么您也应该拥有MS ACCESS。只需将您的数据导入那里,使ref和title成为索引,那么您要做的就是自我联接。 MS Access很烂,但是我敢肯定它可以处理350K行。 理想情况下,您需要在某些公司MSSQL服务器上获得一个数据库(打开票证,与您的经理交谈,等等)。它将以秒为单位计算所有内容,然后您也可以将输出链接到电子表格。