Arrays PowerShell阵列初始化
在PowerShell中初始化阵列的最佳方法是什么 例如,代码Arrays PowerShell阵列初始化,arrays,powershell,Arrays,Powershell,在PowerShell中初始化阵列的最佳方法是什么 例如,代码 $array = @() for($i=0; $i -lt 5;$i++) { $array[$i] = $FALSE } 生成错误 Array assignment failed because index '0' was out of range. At H:\Software\PowerShell\TestArray.ps1:4 char:10 + $array[$ <<<<
$array = @()
for($i=0; $i -lt 5;$i++)
{
$array[$i] = $FALSE
}
生成错误
Array assignment failed because index '0' was out of range.
At H:\Software\PowerShell\TestArray.ps1:4 char:10
+ $array[$ <<<< i] = $FALSE
数组分配失败,因为索引“0”超出范围。
在H:\Software\PowerShell\TestArray.ps1:4 char:10
+$array[$我找到的解决方案是使用New-Object cmdlet初始化一个大小合适的数组
$array = new-object object[] 5
for($i=0; $i -lt $array.Length;$i++)
{
$array[$i] = $FALSE
}
如果我不知道前面的大小,我会使用arraylist而不是数组
$al = New-Object System.Collections.ArrayList
for($i=0; $i -lt 5; $i++)
{
$al.Add($i)
}
还有另一种选择:
for ($i = 0; $i -lt 5; $i++)
{
$arr += @($false)
}
如果尚未定义$arr,则此选项有效
注意-有更好(和更高性能)的方法来实现这一点…请参见下面的示例。如果您希望创建类型化数组,还可以依赖构造函数的默认值:
$array = @()
for($i=0; $i -lt 5; $i++)
{
$array += $i
}
> $a = new-object bool[] 5
> $a
False
False
False
False
False
bool的默认值显然是false,因此这在您的情况下有效。同样,如果您创建一个类型化的int[]数组,您将获得默认值0
我用来初始化数组的另一种很酷的方法是使用以下速记:
> $a = ($false, $false, $false, $false, $false)
> $a
False
False
False
False
False
或者,如果你想初始化一个范围,我有时会发现这很有用:
> $a = (1..5)
> $a
1
2
3
4
5
>$a=(1..5)
>一美元
1.
2.
3.
4.
5.
希望这有点帮助!这里还有两种方法,都非常简洁
$array = 1..5 | foreach { $false }
$arr1 = @(0) * 20
$arr2 = ,0 * 20
原始示例返回一个错误,因为数组创建为空,然后尝试访问第n个元素以为其赋值
这里有许多创造性的答案,许多是我在阅读本文之前不知道的。对于一个小数组来说,这些答案都很好,但正如n0rd指出的,在性能上有很大的差异
在这里,我使用Measure命令来确定每次初始化需要多长时间。正如您可能猜到的,任何使用显式PowerShell循环的方法都比使用.Net构造函数或PowerShell运算符(将在IL或本机代码中编译)的方法慢
总结
新对象
和@(somevalue)*n
速度很快(对于100k元素,大约20k个刻度)
- 使用范围操作符
n..m
创建数组的速度慢10倍(200k个刻度)
- 使用带有
Add()
方法的ArrayList比基线慢1000倍(20米刻度),使用for()
或ForEach对象
(也称为ForEach
,%
)循环通过已经大小的数组也是如此
- 添加
+=
是最糟糕的(只有1000个元素有2米的刻度)
总的来说,我认为数组*n是“最好的”,因为:
- 很快
- 您可以使用任何值,而不仅仅是类型的默认值
- 您可以创建重复值(如需说明,请在powershell提示符下键入:
(1..10)*10-join”“
或('one',2,3)*3
)
- 简洁的语法
唯一的缺点是:
- 不明显。如果你以前没见过这个构造,它的功能就不明显了
但请记住,在许多情况下,如果您希望将数组元素初始化为某个值,那么强类型数组正是您所需要的。如果您将所有内容初始化为$false
,那么该数组是否将保存除$false
或$true
以外的任何内容?如果不存在,则新建Object类型[]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
这并不明显,新对象的文档只是说第二个参数是传递给.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代表array*n,感谢@Scott Saad和Lee Desmond代表新对象,感谢@EBGreen代表ArrayList
感谢@n0rd让我思考性能问题。这里有另一个想法。你必须记住,它是.NET的底层:
$arr = [System.Array]::CreateInstance([System.Object], 5)
$arr.GetType()
$arr.Length
$arr = [Object[]]::new(5)
$arr.GetType()
$arr.Length
结果:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
5
True True Object[] System.Array
5
使用new()
有一个明显的优点:当您在ISE中编程并想要创建一个对象时,ISE将为您提供所有参数组合及其类型的提示。在new object
中,您没有这种提示,您必须记住参数的类型和顺序
或者试试这个主意。与powershell 5.0+配合使用
[bool[]]$tf=((,$False)*5)
以下是另一种典型的方式:
$array = for($i = 0; $i -le 4; $i++) { $false }
告诉我们您正试图实现的目标,也许我们能够为您提供更好的“惯用PowerShell”回答。我从来没有需要在PowerShell中重新创建数组。我没有看到任何人特别提到数组是不可变的。一旦创建,它们就无法修改。非常好,我今天早上试图解决这个问题,我认为你给出了初始化数组的最简洁的方法。谢谢。我的博客上有更多信息,其中有这个主题c2007年9月1日起