9. 数组

编辑说明

重要

Windows PowerShell 语言规范 3.0 于 2012 年 12 月发布,基于 Windows PowerShell 3.0。 此规范不反映 PowerShell 的当前状态。 没有计划更新本文档以反映当前状态。 此处提供了本文档供历史参考。

该规范文档可以作为 Microsoft Word 文档从 Microsoft 下载中心获取:https://www.microsoft.com/download/details.aspx?id=36389。该 Word 文档已被转换用于在 Microsoft Learn 上展示。 转换期间,进行了一些编辑更改,以适应 Docs 平台的格式设置。 已更正某些拼写错误和次要错误。

9.1 简介

PowerShell 支持一个或多个维度的数组,每个维度具有零个或多个 元素。 在维度中,以从零开始的升序对元素进行编号。 可以通过数组下标运算符 []§7.1.4)访问任何单个元素。 数组的维数称为其

元素可以包含任何类型的值,包括数组类型。 具有一个或多个元素的数组,其值属于任何数组类型,称为 交错数组多维数组 具有多个维度,在这种情况下,维度的每一行中的元素数相同。 交错数组的元素可能包含多维数组,反之亦然。

多维数组按行主顺序存储。 数组中的元素数称为该数组的 长度,这是在创建数组时固定的。 因此,可以使用表达式 访问具有长度 N 的 A 的一维 数组中的元素(即 下标)。 B 的二维数组,含有 M 行,每行有 N 列,可以使用表达式 B[0,0], B[0,1], ..., B[0,N-1], B[1,0], B[1,1], ..., B[1,N-1], ..., B[M-1,0], B[M-1,1], ..., B[M-1,N-1]访问其中的元素。 对于具有三个或更多个维度的数组,等等。

默认情况下,数组 多态;例如,其元素不需要具有相同的类型。 例如,

$items = 10,"blue",12.54e3,16.30D # 1-D array of length 4
$items[1] = -2.345
$items[2] = "green"

$a = New-Object 'object[,]' 2,2 # 2-D array of length 4
$a[0,0] = 10
$a[0,1] = $false
$a[1,0] = "red"
$a[1,1] = $null

一个 1 维数组具有类型 type[]、二维数组具有类型 type[,]、三维数组具有类型 type[,,]等,其中 类型 是不受约束的类型数组的对象,或约束数组的约束类型(§9.4)。

所有数组类型都派生自类型 Array(§4.3.2)。

9.2 创建数组

数组是通过 数组创建表达式创建的,该表达式具有以下形式:一元逗号运算符(§7.2.1array-expression§1) 7.1.7)、二进制逗号运算符(§7.3)、范围运算符(§7.4),或 New-Object cmdlet。

下面是数组创建和用法的一些示例:

$values = 10, 20, 30
for ($i = 0; $i -lt $values.Length; ++$i) {
    "`$values[$i] = $($values[$i])"
}

$x = , 10                         # x refers to an array of length 1
$x = @(10)                        # x refers to an array of length 1
$x = @()                          # x refers to an array of length 0

$a = New-Object 'object[,]' 2, 2  # create a 2x2 array of anything
$a[0, 0] = 10                     # set to an int value
$a[0, 1] = $false                 # set to a boolean value
$a[1, 0] = "red"                  # set to a string value
$a[1, 1] = 10.50D                 # set to a decimal value
foreach ($e in $a) {              # enumerate over the whole array
    $e
}

以下内容写入管道:

$values[0] = 10
$values[1] = 20
$values[2] = 30

10
False
red
10.50

未显式初始化的任何元素的默认初始值是该元素类型的默认值(即,$false、零或 $null)。

9.3 数组连接

任意类型和长度的数组可以通过 ++= 运算符连接,这两者都会导致创建新的不受约束的 1 维数组。 现有数组保持不变。 有关更多信息,请参阅 §7.7.3;有关向受约束类型数组中添加内容的讨论,请参阅 §9.4

9.4 约束元素类型

可以创建一个一维数组,通过在数组创建表达式前面加上数组类型转换来使其受到类型约束。 例如,

$a = [int[]](1,2,3,4)   # constrained to int
$a[1] = "abc"           # implementation-defined behavior
$a += 1.23              # new array is unconstrained

创建多维数组的语法需要类型的规范,该类型将成为该数组的约束类型。 但是,通过指定类型 object[],实际上没有任何约束,因为任何类型的值都可以分配给该类型的数组的元素。

连接两个数组(§7.7.3)总是会产生一个不受约束的新数组,即使两个数组都受相同类型的约束。 例如,

$a = [int[]](1,2,3)    # constrained to int
$b = [int[]](10,20)    # constrained to int
$c = $a + $b           # constraint not preserved
$c = [int[]]($a + $b)  # result explicitly constrained to int

9.5 数组作为引用类型

由于数组类型是引用类型,因此可以创建指定数组的变量来引用任何排名、长度和元素类型的任意数组。 例如,

$a = 10,20                     # $a refers to an array of length 2
$a = 10,20,30                  # $a refers to a different array, of length 3
$a = "red",10.6                # $a refers to a different array, of length 2
$a = New-Object 'int[,]' 2,3   # $a refers to an array of rank 2

数组的赋值涉及浅拷贝,也就是说,赋值后的变量指向同一个数组,并不会创建数组的副本。 例如,

$a = 10,20,30
">$a<"
$b = $a         # make $b refer to the same array as $a
">$b<"

$a[0] = 6       # change value of [0] via $a
">$a<"
">$b<"          # change is reflected in $b

$b += 40        # make $b refer to a new array
$a[0] = 8       # change value of [0] via $a
">$a<"
">$b<"          # change is not reflected in $b

以下内容写入管道:

>10 20 30<
>10 20 30<
>6 20 30<
>6 20 30<
>8 20 30<
>6 20 30 40<

9.6 数组作为数组元素

数组的任何元素本身都可以是数组。 例如,

$colors = "red", "blue", "green"
$list = $colors, (,7), (1.2, "yes") # parens in (,7) are redundant; they
                                    # are intended to aid readability
"`$list refers to an array of length $($list.Length)"
">$($list[1][0])<"
">$($list[2][1])<"

以下内容写入管道:

$list refers to an array of length 3
>7<
>yes<

$list[1] 引用一个由 1 个元素构成的数组,即整数 7(通过 $list[1][0]进行访问),如下所示。 将此与以下稍有不同的情况进行比较:

$list = $colors, 7, (1.2, "yes") # 7 has no prefix comma
">$($list[1])<"

此处,$list[1] 指的是标量,即整数 7,通过 $list[1]访问。

请考虑以下示例:

$x = [string[]]("red","green")
$y = 12.5, $true, "blue"
$a = New-Object 'object[,]' 2,2
$a[0,0] = $x               # element is an array of 2 strings
$a[0,1] = 20               # element is an int
$a[1,0] = $y               # element is an array of 3 objects
$a[1,1] = [int[]](92,93)   # element is an array of 2 ints

9.7 负下标

§7.1.4.1对此进行了讨论。

9.8 边界检查

§7.1.4.1对此进行了讨论。

9.9 数组切片

数组切片 是一个不受约束的 1 维数组,其元素是集合中零个或多个元素的副本。 通过下标运算符 []§7.1.4.5)创建数组切片。

9.10 复制数组

可以使用方法 [Array]::Copy将一组连续的元素从一个数组复制到另一个数组。 例如,

$a = [int[]](10,20,30)
$b = [int[]](0,1,2,3,4,5)
[Array]::Copy($a, $b, 2)        # $a[0]->$b[0],
$a[1]->$b[1]
[Array]::Copy($a, 1, $b, 3, 2)  # $a[1]->$b[3],
$a[2]->$b[4]

9.11 枚举数组

虽然可以通过下标运算符遍历数组的每个元素,但我们可以使用 foreach 语句枚举该数组的元素。 对于多维数组,元素按行主要顺序进行处理。 例如,

$a = 10, 53, 16, -43
foreach ($elem in $a) {
    # do something with element via $elem
}

foreach ($elem in -5..5) {
    # do something with element via $elem
}

$a = New-Object 'int[,]' 3, 2
foreach ($elem in $a) {
    # do something with element via $elem
}

9.12 多维数组扁平化

多维数组(如复制(§7.6.3)和串联(§7.7.3)上的某些操作要求将数组 平展;也就是说,要转换为不受约束类型的 1 维数组。 生成的数组将以行优先顺序包含所有元素。

请考虑以下示例:

$a = "red",$true
$b = (New-Object 'int[,]' 2,2)
$b[0,0] = 10
$b[0,1] = 20
$b[1,0] = 30
$b[1,1] = 40
$c = $a + $b

$c 指定的数组包含元素“red”、$true、10、20、30 和 40。