原始示例返回错误,因为数组创建为空,然后您尝试访问第 n 个元素为其分配值。
这里有很多创造性的答案,很多我在阅读这篇文章之前都不知道。对于小型阵列来说,一切都很好,但正如 n0rd 指出的那样,性能存在显着差异。
在这里,我使用 Measure-Command 来找出每次初始化需要多长时间。正如您可能猜到的那样,任何使用显式 PowerShell 循环的方法都比使用 .Net 构造函数或 PowerShell 运算符(将在 IL 或本机代码中编译)的方法慢。
概括
New-Object
并且@(somevalue)*n
速度很快(100k 个元素大约 20k 滴答声)。
- 使用范围运算符创建数组
n..m
要慢 10 倍(200k 滴答声)。
- 将 ArrayList 与该方法一起使用比基线(20M 滴答声)慢 1000 倍,就像使用or (又名, )
Add()
循环通过已经大小的数组一样。 for()
ForEach-Object
foreach
%
- 附加
+=
是最糟糕的(仅 1000 个元素的 2M 滴答声)。
总的来说,我会说array * n是“最好的”,因为:
- 它很快。
- 您可以使用任何值,而不仅仅是类型的默认值。
- 您可以创建重复值(为了说明,请在 powershell 提示符下键入:
(1..10)*10 -join " "
或('one',2,3)*3
)
- 简洁的语法。
唯一的缺点:
- 不明显。如果你以前没有见过这个结构,那么它的作用就不清楚了。
但请记住,对于许多您希望将数组元素初始化为某个值的情况,强类型数组正是您所需要的。如果您将所有内容初始化为$false
,那么该数组是否会保存除$false
or以外的任何内容$true
?如果没有,那么New-Object type[] n
就是“最好”的方法。
测试
创建一个默认数组并确定其大小,然后赋值:
PS> Measure-Command -Expression {$a = new-object object[] 100000} | Format-List -Property "Ticks"
Ticks : 20039
PS> Measure-Command -Expression {for($i=0; $i -lt $a.Length;$i++) {$a[$i] = $false}} | Format-List -Property "Ticks"
Ticks : 28866028
创建布尔数组比对象数组慢一点:
PS> Measure-Command -Expression {$a = New-Object bool[] 100000} | Format-List -Property "Ticks"
Ticks : 130968
这并不明显,New-Object 的文档只是说第二个参数是传递给 .Net 对象构造函数的参数列表。在数组的情况下,参数显然是所需的大小。
附加 +=
PS> $a=@()
PS> Measure-Command -Expression { for ($i=0; $i -lt 100000; $i++) {$a+=$false} } | Format-List -Property "Ticks"
我厌倦了等待它完成,所以 ctrl+c 然后:
PS> $a=@()
PS> Measure-Command -Expression { for ($i=0; $i -lt 100; $i++) {$a+=$false} } | Format-List -Property "Ticks"
Ticks : 147663
PS> $a=@()
PS> Measure-Command -Expression { for ($i=0; $i -lt 1000; $i++) {$a+=$false} } | Format-List -Property "Ticks"
Ticks : 2194398
正如 (6 * 3) 在概念上类似于 (6 + 6 + 6),所以 ($somearray * 3) 应该给出与 ($somearray + $somearray + $somearray) 相同的结果。但是对于数组,+ 是连接而不是加法。
如果 $array+=$element 很慢,您可能会认为 $array*$n 也会很慢,但事实并非如此:
PS> Measure-Command -Expression { $a = @($false) * 100000 } | Format-List -Property "Ticks"
Ticks : 20131
就像Java有一个StringBuilder类来避免在追加时创建多个对象一样,PowerShell似乎有一个ArrayList。
PS> $al = New-Object System.Collections.ArrayList
PS> Measure-Command -Expression { for($i=0; $i -lt 1000; $i++) {$al.Add($false)} } | Format-List -Property "Ticks"
Ticks : 447133
PS> $al = New-Object System.Collections.ArrayList
PS> Measure-Command -Expression { for($i=0; $i -lt 10000; $i++) {$al.Add($false)} } | Format-List -Property "Ticks"
Ticks : 2097498
PS> $al = New-Object System.Collections.ArrayList
PS> Measure-Command -Expression { for($i=0; $i -lt 100000; $i++) {$al.Add($false)} } | Format-List -Property "Ticks"
Ticks : 19866894
范围运算符和Where-Object
循环:
PS> Measure-Command -Expression { $a = 1..100000 } | Format-List -Property "Ticks"
Ticks : 239863
Measure-Command -Expression { $a | % {$false} } | Format-List -Property "Ticks"
Ticks : 102298091
笔记:
- 我在每次运行 (
$a=$null
) 之间清空了变量。
- 测试是在带有 Atom 处理器的平板电脑上进行的;您可能会在其他机器上看到更快的速度。[编辑:在台式机上大约快两倍。]
- 当我尝试多次运行时,会有相当多的变化。寻找数量级而不是确切的数字。
- 在 Windows 8 中使用 PowerShell 3.0 进行测试。
致谢
感谢@halr9000 for array*n,@Scott Saad 和 Lee Desmond for New-Object,以及 @EBGreen for ArrayList。
感谢@n0rd 让我思考性能。