数组简介
了解数组及其在 Ruby 中的使用方法。
简介
数组 是一组数据的集合。例如,一个数组可以包含住在公寓楼里的租户列表、具有特定含义的数字(如员工薪资),或者每个对象代表一名员工并包含多个属性(如薪资、年龄、姓名等)。
在 Ruby 中,数组中的每个元素可以是不同类型的。换句话说,数组就像一个桶,我们可以往里面放苹果、梨子、录音带,甚至几架模型飞机。但通常情况下,数组是同质的,即数组中的所有元素都属于同一类型。
使用数组
但问题是:我们为什么需要数组?为什么要将数据放入数组中?答案很简单:因为数组有助于表示一组数据,并且我们可以对这些数据执行批量操作。假设我们有一个访问过的城市列表:
1arr = ['旧金山', '莫斯科', '伦敦', '纽约']
我们用四个字符串元素初始化了这个数组。Ruby 通过使用方括号来定义数组,因此知道这是一个数组。我们可以对这些数据执行多种有用的运算。例如,获取元素数量,也就是访问过的城市数量:
1# 元素数量 2 3arr = ['旧金山', '莫斯科', '伦敦', '纽约'] 4puts arr.size
我们可以按字母顺序对数组进行排序:
1# 排序数组 2 3arr = ['旧金山', '莫斯科', '伦敦', '纽约'] 4puts arr.sort
或者我们可以遍历数组,逐个处理每个元素:
1# 遍历数组 2 3arr = ['旧金山', '莫斯科', '伦敦', '纽约'] 4 5arr.each do |word| 6 puts "单词 #{word} 有 #{word.size} 个字母" 7end
开发者也可以定义一个空数组:
1arr = []
但为什么一开始就需要一个空数组呢?原因和我们需要一个空桶一样——为了之后往里面添加内容。向数组中添加内容有多种方式,但最常用的两种是:
arr.push(123):使用push方法,该方法在其他语言(如 JavaScript)中也有实现。一些程序员更喜欢这种方式。arr << 123:双箭头符号表示我们要把内容添加到哪里。
一个简单的电话簿程序可能如下所示:
No configuration found for ID: 1772d829f2b726239ce49e282d86e6cce3f4c878295a51a8de4614062d8be7f0
当然,这个电话簿应用非常基础,缺少许多功能。它不会将数据保存到磁盘,也没有按姓名或电话号码搜索的功能,但它仍然能正常运行!我们能够临时保存数据,并在屏幕上显示联系人列表。我们还可以调用 arr.sort 对电话簿中的所有条目进行排序,使结果看起来更整洁。
each 方法
数组由 Array 类表示,该类实现了 each 方法。我们已经熟悉这个方法,因为它常用于对每个元素执行操作。从技术上讲,each 方法接受一个代码块作为参数。如前所述,我们可以将代码块传递给任何方法,程序的后续行为取决于该方法如何处理这个块。
因此,each 方法会针对数组中的每一个元素执行代码块中的内容。换句话说,它为每个项目运行一段(通常是简短的)子程序:
1arr.each do |item| 2 这里是子程序 3 可以有多行代码 4end
这也可以写成一行形式:
1arr.each { |item| ...这里是单行子程序... }
上述示例表明,代码块可以接收参数(如这里的 item)。这个参数由 each 方法提供,就是数组中的下一个元素。do 和 end 之间(或 { 和 } 之间)的内容就是一个代码块。这种方式使得 Ruby 实现了对数组的迭代。这种对数组进行迭代的行为也被称为“数组迭代”、“遍历数组每个元素”或“数组遍历”。
我们可以为参数指定任意名称。在前面的城市遍历示例中,我们使用了 word;在电话簿程序中,使用了 element;现在我们用了 item。唯一的规则是:参数名应对我们和团队来说清晰易懂。理想情况下,像 RuboCop 这样的工具也应认可所选的参数名。
使用 each 方法的写法类似于调用下面示例中的 my_method:
1def my_method(word) 2 puts "单词 #{word} 有 #{word.size} 个字母" 3end
将调用 my_method 与使用 each 方法进行对比:
1arr.each do |word| 2 puts "单词 #{word} 有 #{word.size} 个字母" 3end
遗憾的是,在 Ruby 中我们无法直接将方法名传给 each:
1arr.each my_method
注意:虽然我们可以编写类似的代码来将方法名传递给
each,但:
- 不能以如上所示的方式实现;
- 存在一些限制;
- Ruby 程序员通常不会使用这类写法。
each 方法也存在于其他类型中。迭代是一种程序员经常使用的操作,我们会在一些不太明显的地方看到它的身影。例如,对字符串进行迭代:
1# 字符串迭代 2 3'hello'.each_char { |x| puts x }
或者对范围类型使用 each 方法:
1# 范围类型 2 3(1001..1005).each do |x| 4 puts "我是机器人 #{x}" 5end