Ruby 的数组

在之前的章节中,我们学习了布尔对象、数字对象、字符串对象等,但是有的时候,我们需要将一组对象组合起来成为一个独立的对象,本章节让我们将学习 Ruby 数组,如何创建一个数组以及掌握其常用的实例方法。

1. 数组是什么?

Ruby 数组是任何对象的有序整数索引集合。数组中的每个元素都与一个索引相关,并可通过索引进行获取。—— 官方定义

Ruby 数组是一个包含许多元素的对象。这些元素可以是变量(例如 String,Integer,Hash 等),甚至可以是其他对象(包括构成多维数组的其他数组)。定义中索引指的是数组元素中的一个序号,它从0开始,每个索引对应一个元素。将所有元素放到数组之后,您可以通过各种方法来对数组之中的元素进行操作。

那么如何创建一个数组呢?

2. 如何创建一个数组

Ruby 提供了许多创建数组的方式,数组本质上是 Array 类,所以我们可以使用 Array 的new方法来创建数组。

实例:

> Array.new
=> []

[]表示一个空数组。我们还可以通过向new方法传递参数预设数组的元素数量。

实例:

# 预设里面有3个元素
> Array.new(3) 
=> [nil, nil, nil]

解释:通过预设大小之后的数组的元素为预设数量,所有元素会使用nil代替。

除此之外,我们还可以在创建的时候预设数据。

实例:

> Array[ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]
=> ["Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun"]

通常我们省略 Array,只使用方括号来预设数据。

注意事项:Array.new()参数是数字,用于预设数组的数量,而数组的每一个值都为nil,而Array[]中,参数是一组由逗号分隔的数据,参数里面数据的数量即为数组数据的数量,值及为预设的值。

实例:

> [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]
=> ["Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun"]

经验:我们有几种快速创建数组的方式:

创建字符串数组:

> %w{ cat dog monkey }
=> ["cat", "dog", "monkey"]

创建 Symbol 数组:

> %i{ cat dog monkey }
=> [:cat, :dog, :monkey]

3. 数组的常用实例方法

3.1 判断数组是否为空

使用empty?方法来判断数组是否为空:

实例:

# 定义一个空数组
> days_of_week = []
=> []

days_of_week.empty?
=> true

或者使用size或者length方法,判断数组的长度为0。

实例:

> days_of_week.length == 0
=> true

> days_of_week.size == 0
=> true

3.2 访问数组元素

数组的元素可以通过结合[]方法引用相关元素的索引来访问。例如,要访问数组的第一个和第二个元素。

实例:

# 定义一个数组
> days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]
=> [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]

> days_of_week[0]
=> "Mon"

> days_of_week[1]
=> "Tues"

或者使用at方法:

实例:

> days_of_week.at(0)
=> "Mon"

可以使用 Array 类的firstlast方法访问首个和末尾元素。

实例:

> days_of_week.first
=> "Mon"

> days_of_week.last
=> "Sun"

3.3 查找某一个元素的索引

通常在使用数组时,有必要找出特定元素的索引。这可以通过使用 index 方法来实现,该方法返回第一个元素的索引以匹配指定的条件。例如,确定星期几数组中“星期三”元素的索引值。

实例:

# 定义一个数组
> days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]
=> [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]

> days_of_week.index("Wed")
=> 2

rindex 方法可用于查找数组中的最后一个匹配元素。

实例:

# 定义一个数组
> days_of_week = ["today", "today", "today", "today", "today", "today", "today"]
=> ["today", "today", "today", "today", "today", "today", "today"]

# 返回首个匹配的索引
> days_of_week.index("today")
=> 0

# 返回最后匹配的索引
> days_of_week.rindex("today")
=> 6

3.4 提取数组元素的子集

可以通过指定起点和要提取的元素数来提取数组元素的子集。

例如,从元素1开始并读取3个元素:

实例:

# 定义一个数组
> days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]
=> [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ]

> days_of_week[1, 3]
=> ["Tues", "Wed", "Thu"]

同样,我们可以指定一个范围(请参考 Ruby的范围章节)。

实例:

> days_of_week[1..3]
=> ["Tues", "Wed", "Thu"]

或者,可以使用 Array 类的slice方法。

实例:

> days_of_week.slice(1..3)
=> ["Tues", "Wed", "Thu"]

3.5 合并数组

Ruby 中的数组可以使用多种不同的方法进行连接。

通过+合并。

实例:

days1 = ["Mon", "Tue", "Wed"]
days2 = ["Thu", "Fri", "Sat", "Sun"]
days = days1 + days2

=> ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

使用concat方法

实例:

days1 = ["Mon", "Tue", "Wed"]
days2 = ["Thu", "Fri", "Sat", "Sun"]
days = days1.concat(days2)

=> ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

使用<<方法将元素附加到现有数组。

实例:

days1 = ["Mon", "Tue", "Wed"]
days1 << "Thu" << "Fri" << "Sat" << "Sun"

=> ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

3.6 交集、并集、差集

方法  
- 差集:返回一个新数组,该数组是第一个数组的副本,同时也删除了第二个数组中出现的所有项目。
& 交集:从两个现有数组创建一个新数组,该数组仅包含两个数组共有的元素,重复项会被删除。
| 并集:连接两个数组,重复项会被删除。

实例:

让我们先定义两个数组:

operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "MacOS"]

linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]

创建一个并集,并集操作将一个数组连接到另一个数组,但是删除了所有重复的数组元素。

operating_systems | linux_systems
=> ["Fedora", "SuSE", "RHEL", "Windows", "MacOS", "PCLinuxOS", "Ubuntu"]

接下来创建一个交集,获得两个数组共有的元素。

operating_systems & linux_systems
=> ["Fedora", "SuSE", "RHEL"]

最后我们创建差集,我们不只是使用此运算符删除重复的条目,还需要从左侧操作数指定的数组中删除在右侧操作数指定的数组中也存在的项。

operating_systems - linux_systems
=> ["Windows", "MacOS"]
linux_systems - operating_systems
=> ["PCLinuxOS", "Ubuntu"]

3.7 去除数组元素中重复项

使用uniq方法删除重复项。

linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora", "RHEL", "SuSE"]

linux_systems.uniq
=> ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]

注意事项:在这种情况下,uniq方法不会更改原始数组。如果您真的想从数组中删除重复项,以便更改数组本身,请使用uniq!

实例:

linux_systems
=> ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora", "RHEL", "SuSE"]

linux_systems.uniq!
=> ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]

linux_systems
=> ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]

3.8 向数组中增加或减少元素(push和pop)

Ruby 中的数组可以视为“后进先出”堆栈。当我们想要将新元素放到数组中,它会被插入到最后一个。

我们使用push方法。

实例:

colors = ["red", "green", "blue"]
=> ["red", "green", "blue"]

colors.push "indigo"
=> ["red", "green", "blue", "indigo"]

colors.push "violet"
=> ["red", "green", "blue", "indigo", "violet"]

我们使用pop方法从数组移出元素,数组会从最后一个元素开始移出。pop的返回值是被移出的元素。

实例:

colors.pop
=> "violet"

colors.pop
=> "indigo"

3.9 数组的比较

可以使用==<=>eql?比较 Ruby 数组。

如果两个数组包含相同数量的元素并且每个数组的内容相同,则==返回true

==true的基础上,每个元素的元素类型也相同,则eql?返回true

最后,<=>方法(也称为“飞船”方法)比较两个数组,如果两个数组相等(此处比较方式同==),则返回0;如果元素小于另一个数组中的元素,则返回-1;如果它们大于另一个,则返回1。

实例:

a = [1, 'a', 1.0]
b = [1.0, 'a', 1.0]

a == b   # true
a.eql?b  # false
a <=> b  # 0

3.10 修改数组元素

使用insert方法在数组指定索引位置插入元素。

实例:

colors = ["red", "green", "blue"]
=> ["red", "green", "blue"]

colors.insert( 1, "orange" )
=> ["red", "orange", "green", "blue"]

使用[]=方法,修改数组指定索引位置的值。

实例:

colors = ["red", "green", "blue"]
=> ["red", "green", "blue"]

colors[1] = "yellow"
=> "yellow"

colors
=> ["red", "yellow", "blue"]

[]=方法中使用范围,可以一次修改多个元素。

实例:

colors = ["red", "green", "blue"]
=> ["red", "green", "blue"]

colors[1..2] = "orange", "pink"
=> ["orange", "pink"]

colors
=> ["red", "orange", "pink"]

3.11 删除数组元素

基于索引来删除元素,我们使用delete_at方法。

实例:

colors = ["red", "green", "blue"]
=> ["red", "green", "blue"]

colors.delete_at(1)
=> "green"

colors
=> ["red", "blue"]

基于元素内容来删除的话,使用delete方法。

实例:

colors = ["red", "green", "blue"]
=> ["red", "green", "blue"]

colors.delete("red")
=> "red"

colors
=> ["green", "blue"]

3.12 数组的排序

numbers = [1, 4, 6, 7, 3, 2, 5]
=> [1, 4, 6, 7, 3, 2, 5]

numbers.sort
=> [1, 2, 3, 4, 5, 6, 7]

reverse方法可以将数组倒序排列。

numbers = [1, 4, 6, 7, 3, 2, 5]
=> [1, 4, 6, 7, 3, 2, 5]

numbers.reverse
=> [5, 2, 3, 7, 6, 4, 1]

Tips : 和uniq!方法一样,使用sort!reverse!方法会对调用方法的数组直接进行修改。

4. 小结

在本章中,我们学习了如何在 Ruby 中创建数组,如何对数组进行为空判断、如何访问数组元素、查找索引、提取元素子集、合并数组、去重、排序、删除某一元素以及进行交集、并集、差集操作。