轨道
/
Crystal
Crystal
/
练习
/
Chaitana 的巨型过山车
Chaitana 的巨型过山车

Chaitana 的巨型过山车

学习练习

简介

数组是一种常用的数据结构。因此,有一系列方法可以用来处理数组,包括排序、反转、插入等等。

其中一些方法是破坏性的,也就是说它们会修改原数组。另一些则是非破坏性的,也就是说它们会返回一个新数组,不会修改原数组。

下面是处理数组时最常用的一些方法:

insert

向数组中插入元素时,可以使用 insert 方法,它接收一个下标和一个元素作为实参。 元素会被插入到指定的下标处,数组的其余部分会向右移动。 如果下标越界,就会抛出 IndexError。

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

numbers.insert(5, 5) # => Error: Index out of bounds (IndexError)

delete

当你想要从数组中删除某个特定元素时,可以使用 delete 方法,它接收一个元素作为实参。 该方法会返回被删除的元素。 如果数组中不存在该元素,则返回 nil。

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

first & last

当你想要获取数组的第一个或最后一个元素时,可以使用 first 和 last 方法。 这些方法接收一个可选的实参,用来指定返回多少个元素。 与使用下标 0 或 -1、或者使用范围相比,这样更具可读性。 如果数组为空,就会抛出 Enumerable::EmptyError。

numbers = [1, 2, 3]
numbers.first # => 1
numbers.last  # => 3

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

empty_array = [] of Int32
empty_array.last # => Error: Empty enumerable (Enumerable::EmptyError)

reverse

当你想要反转数组时,可以使用 reverse 方法,它会返回一个元素顺序相反的新数组。 需要注意的是,reverse 返回的是一个新数组,不会修改原数组。 如果你想修改原数组,可以在方法名末尾加上 !。

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

numbers.reverse! # => [3, 2, 1]
numbers          # => [3, 2, 1]

Concat(+)

追加方法(<<)在向数组添加对象时很有用。 不过,在合并两个数组时,可以使用 + 运算符,它会返回一个包含两个数组所有元素的新数组。

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

如果你把一个数组追加到另一个数组,这个数组会作为单个元素被添加进去。

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

empty?

当你想要检查数组是否为空时,可以使用 empty? 方法,如果数组为空就返回 true,否则返回 false。 与用 0 比较数组的长度相比,这样更具可读性。

[].empty? # => true
[1, 2, 3].empty? # => false

index

当你想要获取某个元素在数组中的下标时,可以使用 index 方法,它接收一个元素作为实参。 如果数组中不存在该元素,则返回 nil。

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

size

当你想要知道数组中元素的个数时,可以使用 size 方法。

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

count

当你想要统计某个元素在数组中出现的次数时,可以使用 count 方法。

fruits = ["apple", "banana", "apple"]
fruits.count("apple")      # => 2
fruits.count("banana")     # => 1
fruits.count("watermelon") # => 0

sort

当你想要对数组排序时,可以使用 sort 方法,它会返回一个元素已排好序的新数组。 和 reverse 一样,这个方法返回的是一个新数组,不会修改原数组。

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

numbers.sort! # => [1, 2, 3]
numbers       # => [1, 2, 3]

说明

Chaitana 经营着一座非常受欢迎的主题公园。 在风景优美的园区正中央,她只有一座游乐设施:The Biggest Roller Coaster in the World(TM)。 尽管只有这一个游乐项目,人们还是从世界各地赶来,排上几个小时的队,只为有机会坐上 Chaitana 的超级过山车。

这个项目有两条队列,每条都用一个array表示:

  1. 普通队列
  2. 快速队列(也叫 Fast-track),人们额外付费就能优先入场。

你需要写一些代码,来更好地管理公园里的游客。 你得尽快实现下面这些函数,免得游客(还有你的老板 Chaitana!)发脾气。

1. 把某人加入队列

定义ColossalCoaster.add_to_queue方法,它接收 4 个实参<express_queue>, <normal_queue>, <ticket_type>, <person_name>,并返回加入了此人姓名后的相应队列。

  1. <ticket_type>是一个Int32,其中 1 == express_queue,0 == normal_queue。
  2. <person_name>是要加入相应队列的那个人的名字(类型为String)。
express_queue = ["Tony", "Bruce"]
normal_queue = ["RobotGuy", "WW"]
ColossalCoaster.add_to_queue(express_queue, normal_queue, 1, "RichieRich")
# => ["Tony", "Bruce", "RichieRich"]

2. 我的朋友在哪儿?

有个人来公园来晚了,却想加入朋友们正在排队的那条队列。 但他不知道朋友们排在哪儿,又没有手机信号,没法打电话联系他们。

定义ColossalCoaster.find_my_friend方法,它接收 2 个实参queue和friend_name,并返回这个人的名字在队列中的位置。

  1. <queue>是排队人群组成的array。
  2. <friend_name>是你要查找下标的那个朋友的名字(即他在队列中的位置)。
ColossalCoaster.find_my_friend(["Natasha", "Steve", "T'challa", "Wanda", "Rocket"], "Steve")
# => 1

3. 我能加入他们吗?

既然已经找到了他们的朋友(见上面的任务 2),这位迟到的人就想排到朋友所在的位置。 定义ColossalCoaster.add_with_friends方法,它接收 3 个实参queue、friend_name和person_name。

  1. <queue>是排队人群组成的array。
  2. <friend_name>是朋友的名字,这个人要加到这个朋友所在的位置。
  3. <person_name>是要加到该下标位置的人的名字。

返回加入了这位迟到者名字后的队列。

ColossalCoaster.add_with_friends(["Natasha", "Steve", "T'challa", "Wanda", "Rocket"], "Steve", "Bucky")
# => ["Natasha", "Bucky", "Steve", "T'challa", "Wanda", "Rocket"]

4. 队列里的讨厌鬼

你刚从队列那边听说,有个特别讨厌的家伙又推又嚷,还在捣乱。 你得把这个捣蛋鬼赶出去,因为他行为不端!

定义ColossalCoaster.remove_from_queue方法,它接收 2 个实参queue和person_name。

  1. <queue>是排队人群组成的array。
  2. <person_name>是需要被赶出去的那个人的名字。

返回去掉这个讨厌鬼名字后的队列。

ColossalCoaster.remove_from_queue(["Natasha", "Steve", "Eltran", "Wanda", "Rocket"], "Eltran")
# => ["Natasha", "Steve", "Wanda", "Rocket"]

5. 对队列排序

出于管理需要,你要把某个队列里的所有名字按字母顺序排好。

定义ColossalCoaster.sorted_queue方法,它接收 1 个实参queue(排队人群组成的array)。 该方法应返回排好序的array副本。

ColossalCoaster.sorted_queue(["Natasha", "Steve", "Eltran", "Natasha", "Rocket"])
# => ['Eltran', 'Natasha', 'Natasha', 'Rocket', 'Steve']
通过 GitHub 编辑 链接将在新窗口或新标签页中打开
Crystal Exercism

准备好开始 Chaitana 的巨型过山车 了吗?

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