我需要使用我输入的确切行数(数据库是预定义的)搜索数据库,它包含> 11800个条目.
你能帮我找一下这个慢的原因吗?
码:
$Dict = Get-Content "C:\Users\----\Desktop\Powershell Program\US.txt" if($Right -ne "") { $Comb = $Letter + $Right $total = [int]0 $F = "" do { $F = $Dict | Select-Object -Index $total if($F.Length -eq $Num) { if($F.Chars("0") + $F.Chars("1") -eq $Comb) { Add-Content "C:\Users\----\Desktop\Powershell Program\Results.txt" "$F" } } $total++ Write-Host $total } until([int]$total -gt [int]118619) $total = [int]0 $F = "" }
如何逐行搜索/匹配处理加快这一行?我是通过多线程做的吗?如果是这样的话?
看起来你在powershell之前至少已经知道了另一种语言,并且最初基本上复制了你在另一种语言中所做的事情.这是学习新语言的好方法,但当然在开始时你最终可能会遇到一些有点奇怪或不具备性能的方法.首先,我想分解您的代码实际执行的操作,作为一个粗略的概述:
>一次读取文件的每一行并将其存储在$Dict变量中.
>循环次数与行数相同.
>在循环的每次迭代中:
>获取与循环迭代匹配的单行(主要通过另一次迭代,而不是索引,稍后再详述).
>获取该行的第一个字符,然后获取第二个字符,然后将它们组合起来.
>如果它等于预定的字符串,请将此行追加到文本文件中.
步骤3-1是真正放慢这一点的原因
要了解原因,您需要了解PowerShell中的管道.接受和处理管道的Cmdlet会占用一个或多个对象,但它们一次处理一个对象.他们甚至无法访问管道的其余部分.
Select-Object cmdlet也是如此.因此,当您将一个包含18,500个对象的数组放入其中并将其输入Select-Object -Index 18000时,您需要发送17,999个对象进行检查/处理,然后才能为您提供所需的对象.您可以看到索引越大,所用时间越长越长.
由于你已经有了一个数组,你可以通过方括号[]的索引直接访问任何数组成员,如下所示:
$Dict[18000]
对于给定的数组,无论索引是什么,都需要相同的时间.
现在,对于Select-Object -Index的单次调用,您可能不会注意到它需要多长时间,即使索引非常大;问题是你已经在整个数组中循环,所以这很复杂.
你基本上必须做1..18000的总和,这大约是或大约162,000,000次迭代! (感谢user2460798纠正我的数学)
证明
我测试了这个.首先,我创建了一个包含19,000个对象的数组:
$a = 1..19000 | %{"zzzz~$_"}
然后我测量了两种访问它的方法.首先,使用select -index:
measure-command { 1..19000 | % { $a | select -Index ($_-1 ) } | out-null }
结果:
TotalMinutes : 20.4383861316667 TotalMilliseconds : 1226303.1679
然后使用索引运算符([]):
measure-command { 1..19000 | % { $a[$_-1] } | out-null }
结果:
TotalMinutes : 0.00788774666666667 TotalMilliseconds : 473.2648
结果非常引人注目,使用Select-Object需要近2,600倍的时间.
计数循环
以上是导致您大幅放缓的唯一因素,但我想指出其他一些事情.
通常在大多数语言中,您将使用for循环进行计数.在PowerShell中,这将是这样的:
for ($i = 0; $i -lt $total ; $i++) { # $i has the value of the iteration }
简而言之,for循环中有三个语句.第一个是在循环开始之前运行的表达式. $i = 0将迭代器初始化为0,这是第一个语句的典型用法.
接下来是有条件的;这将在每次迭代时进行测试,如果返回true,循环将继续.这里$i -lt $total比较检查以查看$i是否小于$total的值,其他一些变量在其他地方定义,可能是最大值.
最后一个语句在循环的每次迭代中执行. $i与$i = $i 1相同所以在这种情况下我们在每次迭代时递增$i.
它比使用do / until循环更简洁,并且更容易理解,因为for循环的含义是众所周知的.
其他说明
如果您对有关工作代码的更多反馈感兴趣,请查看Code Review.请在发布之前仔细阅读相关规则.