跳至内容

数组

一个 数组 是一个有序的、用整数索引的泛型集合,包含特定类型 T 的元素。

数组通常使用数组字面量创建,用方括号 ([]) 表示,每个元素之间用逗号 (,) 分隔。

[1, 2, 3]

泛型类型参数

数组的泛型类型参数 T 从字面量内元素的类型推断得出。当数组的所有元素都具有相同的类型时,T 等于该类型。否则,它将是所有元素类型的联合。

[1, 2, 3]         # => Array(Int32)
[1, "hello", 'x'] # => Array(Int32 | String | Char)

可以通过在闭合方括号后紧跟着 of 和一个类型来指定显式类型。这将覆盖推断出的类型,例如,它可以用来创建一个最初只包含某些类型的数组,但之后可以接受其他类型。

array_of_numbers = [1, 2, 3] of Float64 | Int32 # => Array(Float64 | Int32)
array_of_numbers << 0.5                         # => [1, 2, 3, 0.5]

array_of_int_or_string = [1, 2, 3] of Int32 | String # => Array(Int32 | String)
array_of_int_or_string << "foo"                      # => [1, 2, 3, "foo"]

空数组字面量始终需要类型说明

[] of Int32 # => Array(Int32).new

百分号数组字面量

字符串数组符号数组 可以使用百分号数组字面量创建

%w(one two three) # => ["one", "two", "three"]
%i(one two three) # => [:one, :two, :three]

数组类类型字面量

Crystal 支持数组和数组类类型的附加字面量。它由类型的名称组成,后面是包含在大括号 ({}) 中的元素列表,每个元素之间用逗号 (,) 分隔。

Array{1, 2, 3}

这个字面量可以与任何类型一起使用,只要它有一个无参数构造函数并响应 <<

IO::Memory{1, 2, 3}
Set{1, 2, 3}

对于像 IO::Memory 这样的非泛型类型,这等同于

array_like = IO::Memory.new
array_like << 1
array_like << 2
array_like << 3

对于像 Set 这样的泛型类型,泛型类型 T 从元素类型推断出来,与数组字面量相同。上述等同于

array_like = Set(typeof(1, 2, 3)).new
array_like << 1
array_like << 2
array_like << 3

类型参数可以作为类型名称的一部分明确指定

Set(Int32){1, 2, 3}

星号扩展

星号运算符可以在数组和数组类字面量中使用,以一次性插入多个值。

[1, *coll, 2, 3]
Set{1, *coll, 2, 3}

唯一的要求是 coll 的类型必须包含 Enumerable。上述等同于

array = Array(typeof(...)).new
array << 1
array.concat(coll)
array << 2
array << 3

array_like = Set(typeof(...)).new
array_like << 1
coll.each do |elem|
  array_like << elem
end
array_like << 2
array_like << 3

在这些情况下,泛型类型参数也会使用 coll 的元素进行推断。