Powershell 的数据结构 Array

Powershell 的数据结构 Array

简要说明, 数组是 pwshSystem.Array 的包装

创建方式

创建一般以 @() 格式, 列表是不可变的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$data = @() 
$null -eq $data[9000] # no exception
Get-Member -InputObject $data
$data.IsFixedSize
$data.GetHashCode()

$data +=1
$data.GetHashCode()

$v1 = ,1
$v2 = 1,2
$v3 = @(1,2,3)
$v4 = 3..5
$v5 = 'a'..'i'
$v6 = 1..-2
[char[]]$v7= 'A','B'

$table = [ordered]@{
'v1'=$v1
'v2'=$v2
'v3'=$v3
'v4'=$v4
'v5'=$v5
'v6'=$v6
'v7'=$v7
}
#
$table
$table.Values.ForEach({$_.GetType()})
$v7 -as [int32[]]
# 65
# 66
$v7[0] -as [int32] # 65
@(66,69,71).ForEach([char])
# B
# E
# G
$v3[-1]
# 3
$v5[-1,-3]
# i
# g
$v5[-1..-3]
# i
# h
# g
$v5[2,3+5..7]
# c
# d
# f
# g
# h

可变数组与效率

使用 System.Collections.GenericSystem.Linq 优化代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using namespace System.Collections.Generic
using namespace System.Linq
$list = [List[string]]::new(([int32]::MaxValue)/2)
$s = Get-Date
do{
$cur +=1
$list.Add('AS')
}until ($cur -eq 20000)
(Get-Date) - $s
$s = Get-Date
$list.AddRange([Enumerable]::Repeat('BS',20000)) # 更快
(Get-Date) - $s
$list[0..2]

一些要点

-eq /-ne 遇上数组

-eq 运算符对前边的每一项进行对比返回匹配的值而不是布尔值, 对于含有 $null 值的序列, 需要注意调用顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

$Array= @($null)
$Array.Length
$Array -eq $null # 空输出
(@('one',$null,'three') -eq $null).Length
# 1
(@('one',$null,'three') -eq $null).GetType()
# Object[]
(@('one',$null,'three') -eq $null)[0] -eq $null
# True
$null -eq $Array
# false
[Object]::Equals($Array,$null)
# false

@(1,$null,3) | foreach ({ "$($_ ; $null -eq $_)" })
# 1 False
# True
# 3 False

$data = @('op','gx','ii')
$data -ne 'gx'
# op
# ii

-join -replace -split

这些属于字符串方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@(1,2,3) -join '-'
[string]::Join("-",@(1,2,3))
Join-String -InputObject @(1,2,3) -Separator '-'
# 1-2-3
Join-String -InputObject @(1,2,3) -Separator '-' -OutputPrefix "@" -OutputSuffix ".txt"
# @1-2-3.txt
@("PPPE-203","MUKC-077") -split '-'
#PPPE
#203
#MUKC
#077
@("PPPE-203","MUKC-077") -replace '-','_'
#PPPE_203
#MUKC_077

-contains -in -match

1
2
3
4
5
6
7
8
9
10
11
12
13
 @(1,2,3) -contains 1
# true
1 -in @(1,2,3)
# true
$data = 'game loaded with P1','game unload with P2','game exits'
$data -match "\w?load"
#game loaded with P1
#game unload with P2
$m = 'game unload with P2' -match 'game\s(?<status>\w*load)\swith\sP(?<player>\d+)'
if($m){
$Matches
}