跳至內容

陣列

陣列是一個有序且以整數索引的泛型集合,其中包含特定型別 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}

Splat 展開

Splat 運算子可以用於陣列和類陣列常值中,以一次插入多個值。

[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 的元素進行推斷。