轨道
/
Crystal
Crystal
/
练习
/
语言列表
语言列表

语言列表

学习练习

简介

数组是一种可变的数据结构,用于存储特定类型的元素集合。 数组是一种可索引的数据结构。 数组可变意味着,如果对数组调用了一个会修改数组的方法,数组就会被修改。 也就是说,它不会创建新数组,而是修改现有的数组。

要创建数组,可以使用数组字面量语法([]),在其中用逗号分隔各个元素。

[1, 2, 3] # => [1, 2, 3]

Crystal 会根据元素推断数组的类型。

[1, 2, 3].class # => Array(Int32)

多类型数组

前面提到数组是特定类型的元素集合,但你仍然可以使用联合类型创建包含多种类型的数组。 这样数组就可以包含联合类型中指定的任意类型的元素。 Crystal 会根据元素推断数组的类型。

[1, "2", 3.0] # => [1, "2", 3.0]

[1, "2", 3.0].class # => Array(Int32 | Float64 | String)

多维数组

多维数组就是数组的数组。 也就是说,数组中的每个元素本身也是一个数组。 当你想以表格形式存储数据时,这会很有用。 要定义多维数组,你可以写出数组的数组字面量,也可以使用Array.new构造函数。

[[1, 2], [3, 4]]                    # => [[1, 2], [3, 4]]
numbers = Array(Array(Int32)).new() # => []
numbers << [1, 2]                   # => [[1, 2]]

向数组添加元素

要向数组添加元素,可以使用 <<(追加)运算符。

[1, 2, 3] << 4 # => [1, 2, 3, 4]

要添加的元素的类型必须与数组的类型相同,否则会引发错误。

numbers : Array(Int32 | Float64) = [1, 2, 3]
numbers << 4.0
numbers # => [1, 2, 3, 4.0]

numbers << "5" # => Error: no overload matches 'Array(Int32 | Float64)#<<' with type String

数组的大小

和String一样,你可以使用 size方法获取数组的大小。

[1, 2, 3].size # => 3

空数组

在创建空数组时,编译器无法推断数组类型。 因此,你需要指定数组的类型。 可以通过指定数组的类型、使用of关键字,或者使用数组初始化语法Array(T).new来实现。

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

访问元素

和String一样,你可以使用 [](下标)运算符访问数组中的元素,并传入要访问元素的下标。 如果下标越界,会引发IndexError。

[1, 2, 3][0] # => 1

[1, 2, 3][3] # => Index out of bounds (IndexError)

也可以使用范围来访问元素。

[1, 2, 3][0..1] # => [1, 2]

从范围创建数组

要从范围创建数组,可以使用 to_a 方法。 当你想创建一个数字数组时,这会很有用。

(1..3).to_a # => [1, 2, 3]

从字符串创建数组

要从字符串创建数组,可以使用 split方法。 它让你用分隔符把一个字符串拆分成字符串数组。

"1,2,3".split(",") # => ["1", "2", "3"]

还可以使用 chars方法从字符串获取字符数组。

"123".chars # => ['1', '2', '3']

要把Char或String数组转换为String,可以使用 join方法,它接受一个分隔符作为实参。

['1', '2', '3'].join(".") # => "1.2.3"

从数组中删除元素

当你想从数组末尾删除元素时,可以使用 pop方法,它接受一个可选实参,指定从数组末尾删除多少个元素。 该方法返回被删除的元素。 如果数组为空,会引发IndexError。

numbers = [1, 2, 3]
numbers.pop # => 3
numbers     # => [1, 2]

empty_numbers = [] of Int32
empty_numbers.pop # => Index out of bounds (IndexError)

当你想删除数组中指定下标的元素时,可以使用 delete_at方法,它接受要删除元素的下标作为实参。 如果数组为空,会引发IndexError。

numbers = [1, 2, 3]
numbers.delete_at(1) # => 2
numbers              # => [1, 3]

empty_numbers = [] of Int32
empty_numbers.delete_at(0) # => Index out of bounds (IndexError)

修改数组中的值

当你想修改数组中指定下标的元素时,可以使用 []=(下标赋值)运算符,它接受要修改元素的下标和新值作为实参。 如果下标越界,会引发IndexError。

numbers = [1, 2, 3]
numbers[1] = 4
numbers # => [1, 4, 3]

numbers[3] = 5 # => Index out of bounds (IndexError)

说明

在这个练习中,你需要实现一些方法来操作一个编程语言数组。

1. 定义一个返回空语言数组的方法

定义 LanguageList.list 方法,它不接受任何实参,并返回一个类型为 Array(String) 的空数组。

LanguageList.list()
# => []

2. 定义一个向数组中添加语言的方法

定义 LanguageList.add 方法,它接受 2 个实参(一个_语言数组_和一个_语言_的字符串字面量)。 该方法应返回添加了新语言后的数组,新语言位于数组末尾。

language_list = LanguageList.list()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]

3. 定义一个从数组中移除语言的方法

定义 LanguageList.remove 方法,它接受 1 个实参(一个_语言数组_)。 该方法应返回去掉最后一项后的数组。 假设数组至少有 1 项。

language_list = LanguageList.list()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
language_list = LanguageList.remove(language_list)
# => ["Crystal"]

4. 定义一个返回数组中第 n 项的方法

定义 LanguageList.at 函数,它接受 2 个实参(一个_语言数组_和一个下标)。 该方法应返回数组中下标为 n 的语言。 假设该下标处总是存在一种语言。

language_list = LanguageList.new()
# => []
language_list = LanguageList.add(language_list, "Crystal")
# => ["Crystal"]
language_list = LanguageList.add(language_list, "Ruby")
# => ["Crystal", "Ruby"]
LanguageList.at(language_list, 1)
# => "Ruby"

5. 定义一个解析语言字符串的方法

定义 LanguageList.parse 方法,它接受 1 个实参(一个由逗号分隔的语言字符串字面量)。 该方法应返回一个语言数组。

LanguageList.parse("Crystal, Ruby")
# => ["Crystal", "Ruby"]
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Crystal Exercism

准备好开始 语言列表 了吗?

注册 Exercism,借助 26 个概念142 个练习 和真人导师指导,学习并掌握 Crystal,全部免费。