## 6.数组 阵列可以视为机架。 你可以将任何东西 1 放在机架中,以类似的方式可以将任何东西放在阵列中。 一个机架包含许多架子或隔层。 如果你可以数数,则可以在每个隔间上放置数字,可以认为机架是用于存储某些东西的空间阵列。 每个隔间可以用数字标识,因此易于识别。 阵列是可供程序员使用的机架。 让我们看一个示例以了解更多信息。 在下面输入程序并执行 ```rb # array.rb my_array = [] my_array << "Something" my_array << 123 my_array << Time.now my_array.each do |element| puts element end ``` 这就是你将获得输出的方式 ```rb Something 123 Tue Feb 02 18:10:06 +0530 2010 ``` 让我们遍历程序,以`my_array = []`行,在其中声明一个名为`my_array`的数组,它是一个没有任何内容的空数组。 `[]`表示一个空数组,我们将其分配给`my_array`。 这样做后,我们在以下语句中填充一些值 ```rb my_array << "Something" my_array << 123 my_array << Time.now ``` 我们将元素追加到数组。 在第一条语句中,我们附加字符串常量`“Something”`,在第二条语句中,我们附加整数`123`,在第三条语句中,我们附加当前时间。 如果你猜对了,我们已经使用`<<`运算符将值附加到数组。 到现在为止,我们已经创建了一个名为`my_array`的数组,并将其放入其中。 现在,我们必须查看所输入的内容。为此,我们使用`<array_name>.each`(每个数组名称点一个点)。 此方法提取数组的每个元素。 因此,对于 my_array,我们使用`my_array.each` 好了,我们必须对数组的每个元素做一些事情。 为此,我们添加了`do … end`,我们可以在其中进行某些操作,因此我们的代码将转换为 ```rb my_array.each do end ``` 我们必须将数组的每个元素捕获到一个变量中,让我们使用名为`element`的变量来完成这项工作,因此我们使用以下代码捕获每个元素 ```rb my_array.each do |element| end ``` 注意我们如何将`element`变量放在`|`和`|`之间。 我们已经捕获了数组的每个元素,现在该怎么办? 我们将使用`puts`语句打印它。 这样我们的数组就可以成功打印了。 以下程序也与以前的程序相同,但是我们使用`Array.new`而不是`[]`来表示`my_array`是一个数组 <sup class="footnote">[ [23](#_footnotedef_23 "View footnote.") ]</sup> ```rb # array_1.rb my_array = Array.new my_array << "Something" my_array << 123 my_array << Time.now my_array.each do |element| puts element end ``` 我将编写另一个程序,该程序将使用`for`构造遍历数组的每个元素,如下所示 ```rb # array_2.rb my_array = Array.new my_array << "Something" my_array << 123 my_array << Time.now for element in my_array puts element end ``` 输出量 ```rb Something 123 2012-08-10 19:19:47 +0530 ``` 还有第三种创建数组的方法。 请仔细查看下面的程序。 看`my_array = [ "Something", 123, Time.now ]`。 仔细看,我们有`my_array`那是一个我们要为其分配数组的变量,其设置为`[ "Something", 123, Time.now ]`。 也就是说,在这种情况下,我们在同一条语句中声明并向`my_array`添加了数组元素或值。 请注意,我们将数组的元素放在方括号中,这是声明和填充数组的另一种方法。 因此,程序 [array_3.rb](code/array_3.rb) 的工作原理与 [array_1.rb](code/array_1.rb) 和 [array.rb](code/array.rb) 完全相同,但更加简洁。 与许多语言不同,Ruby 让程序员选择自己的编码风格。 ```rb # array_3.rb my_array = [ "Something", 123, Time.now ] puts my_array.join("\n") ``` Output ```rb Something 123 Wed Feb 03 17:37:36 +0530 2010 ``` 直到最后一个示例,我们使用每个示例来循环访问数组元素,现在我们将使用一种新的循环,即`for`循环,因此这里是一个代码 ```rb # array_for.rb my_array = Array.new my_array.push("Something") my_array.push 123 my_array << Time.now for element in my_array puts element end ``` Output ```rb Something 123 2014-11-12 10:37:22 +0530 ``` 请参阅上面我们采用的新构造,这是: ```rb for element in my_array puts element end ``` 注意这一行`for element in my_array`。 这等效于`my_array.each |element` | 在前面的示例中。 `for`循环我个人觉得有点优雅。 因此,就像`each`一样,`my_array`中的每个元素都被加载到`element`中,这在循环块中可供程序员使用。 在这里,我们只使用`puts element`打印它。 ### 6.1。 有关阵列的更多信息 现在让我们看一些数组函数。 为此,我们将使用我们最喜欢的 irb 而不是文本编辑器 ```rb >> array = Array.new => [] ``` 好的,在上面的语句中,我们看到我们使用`Array.new`创建了一个名为`array`的数组。 `Array.new`创建一个空数组。 还有另一种创建数组的方法。 我们可以通过直接指定数组中包含的值来创建它,如下所示 ```rb >> array = ["Something", 123, Time.now] => ["Something", 123, Tue Feb 02 20:30:41 +0530 2010] ``` 在上面的语句中,我们创建了一个包含三个对象的数组。 必须在数组中的值在方括号`[`和`]`之间给出。 数组中的每个对象都用逗号分隔。 通过不提供`[`和`]`之间的值,我们甚至可以创建一个空数组,如下所示 ```rb >> array = [] => [] ``` 在上面的示例中,空白`[]`与 Array.new 的工作相同。 让我们使用`Array.new`中的参数创建数组,如下所示 ```rb >> array = Array.new("Something", 123, Time.now) ArgumentError: wrong number of arguments (3 for 2) from (irb):3:in `initialize' from (irb):3:in `new' from (irb):3 from :0 ``` 如你所见,它失败了! 不要那样使用。 好的,现在让我们在`array`上进行一些尝试,首先要获取`array`中有多少个元素,我们可以使用`length`函数,如下所示: ```rb >> array.length => 3 ``` `join`函数将许多数组元素连接在一起并返回它。 因此,当将数组中的元素连接在一起时,这就是结果: ```rb >> array.join(', ') => "Something, 123, Tue Feb 02 20:30:41 +0530 2010" ``` 请注意,当数组元素作为字符串连接时,我们将字符串`', '`传递给`join`。 我们传递的字符串将插入它们之间。 我们已经创建了一个数组,并且其中包含一些东西,如果我们想添加一些东西,该怎么办? 为此,我们使用`push`方法。 在下面的示例中,我们将数字 5 推入`array`,然后看到数组得到扩展,最后将 5 附加到`array`。 ```rb >> array.push(5) => ["Something", 123, Tue Feb 02 20:30:41 +0530 2010, 5] ``` `pop`方法的作用与`push`相反,它弹出或删除数组的最后一个元素。 参见下面的示例,我们弹出一个元素,然后弹出最后一个元素 5。 ```rb >> array.pop => 5 ``` 弹出后,让我们看看`array`中的内容 ```rb >> array => ["Something", 123, Tue Feb 02 20:30:41 +0530 2010] ``` 我们看到数组大小减少了一个,最后一个元素 5 丢失了。 它不是只需要在`push`中给出固定值,而是可以将变量和 Ruby 表达式以及任何对象作为参数提供给 push。 你可以在下面看到我们将 2 提升到 10 的幂到数组,最后将 1024 添加到数组。 ```rb >> array.push 2**10 => ["Something", 123, Tue Feb 02 20:30:41 +0530 2010, 1024] ``` 索引数组元素。 数组的第一个元素的索引号为 0,并且继续(理论上一直到无穷大)。 如果要访问索引中的元素,则他要做的就是将索引号放在方括号之间。 在下面的示例中,我们访问名为`array`的数组的第三个元素,因此我们将其键入如下 ```rb >> array[2] => Tue Feb 02 20:30:41 +0530 2010 ``` `pop`方法接受一个 I​​nteger 作为参数,用于弹出`n`数组的最后一个元素。 ```rb >> array.pop(2) => [Tue Feb 02 20:30:41 +0530 2010, 1024] >> array => ["Something", 123] ``` 如你所见,第三个元素被弹出,因此可以随机弹出。 我们可以一次将许多元素推入数组。 考虑下面的代码片段 ```rb >> array.push 5, "Who am I?", 23.465*24 => ["Something", 123, 5, "Who am I?", 563.16] ``` 我们首先将 3 个新元素推入数组,然后得到一个更大的元素。 现在我们弹出最后 3 个元素 ```rb >> array.pop 3 => [5, "Who am I?", 563.16] ``` 如你所见,数组的大小减小了,现在只有两个元素。 ```rb >> array => ["Something", 123] ``` 还有另一种在数组中追加元素的方法,它使用小于运算符`<<`的 double,使一些元素随其推入数组,如下所示: ```rb >> array << "a new element" => ["Something", 123, "a new element"] >> array << 64 => ["Something", 123, "a new element", 64] ``` 如你在上面看到的,我们使用`<<`运算符将字符串常量`“a new element”`和`64`附加到数组。 你可以使用`max`和`min`函数在数组中找到最大值和最小值,如下所示: ```rb >> nums = [1, 2, 64, -17, 5 ,81] => [1, 2, 64, -17, 5, 81] >> nums.max => 81 >> nums.min => -17 ``` 如上例所示,我们创建了一个名为`nums`的数组,其中包含一些数字,`nums.max`返回该数组中的最大值,`nums.min`返回该数组中的最小值。 ### 6.2。 数组挖掘 看一下在 irb 中执行的一个简单代码段,我们有一个嵌套数组,可以说我们要访问字符串元素`“Treasure”`,可以使用 dig 方法,如下所示 ```rb >> array = [1, 5, [7, 9, 11, ["Treasure"], "Sigma"]] => [1, 5, [7, 9, 11, ["Treasure"], "Sigma"]] >> array.dig(2, 3, 0) => "Treasure" ``` ### 6.3。 设定操作 对于那些了解集合论的人,你必须了解交集,并集。 我在学校时读过关于集合论的文章,​​但现在已经忘记了。 你可以将数组视为集合并对其执行许多操作。 以下是一些我在 irb 上试过的例子,让我们参加一个大学排球队,其中有些人叫 Ashok,Chavan,Karthik,Jesus 和 Budha。 如果你列出板球队的名单,那就有 Budha,Karthik,Ragu 和 Ram。 现在让我们用 ruby 对其进行编码。 为了收集排球队成员,我们创建了一个数组,如下所示 ```rb >> volleyball=["Ashok", "Chavan", "Karthik", "Jesus", "Budha"] => ["Ashok", "Chavan", "Karthik", "Jesus", "Budha"] ``` 以类似的方式,我们创建了另一个数组,其中包含板球队中球员的姓名,如下所示 ```rb >> cricket=["Budha", "Karthik", "Ragu", "Ram"] => ["Budha", "Karthik", "Ragu", "Ram"] ``` 因此,我们有两组人。 现在要找出谁在排球和板球运动中,我们所需要做的就是使用&运算符对两个数组进行 AND(或取交) ```rb >> volleyball & cricket => ["Karthik", "Budha"] ``` 从上面的代码片段中可以看到,`&`(和)运算符会嗅出两个数组中都存在的那些元素。 在数学中,这种东西称为交集。 让我们说在另一种情况下,我们想找出所有排球和板球队的人。 为此,我们使用 or 运算符`|`。 现在应用它 ```rb >> volleyball | cricket => ["Ashok", "Chavan", "Karthik", "Jesus", "Budha", "Ragu", "Ram"] ``` 如你所见,我们获得了排球队和板球队成员的名字。 | (或)运算符不同于+(加号)运算符。 让我们增加排球队和板球队 ```rb >> volleyball + cricket => ["Ashok", "Chavan", "Karthik", "Jesus", "Budha", "Budha", "Karthik", "Ragu", "Ram"] ``` 从上面的代码片段中可以看到,名称 Karthik 和 Budha 是重复的。 当我们使用|时,这不会发生。 (OR)运算符。 现在让我们找出哪些球员只为排球队效力。 为此,我们将使用`–`(减号)运算符减去排球队的板球运动员,如下所示 ```rb >> volleyball - cricket => ["Ashok", "Chavan", "Jesus"] ``` 因此,我们看到排球队中只有三名球员。 因此,如果你是数学家,你会对 Ruby 感到满意。 ### 6.4。 空数组为真 Ruby 开发人员还必须了解其他内容。 它关于条件和空数组。 启动你的 irb 并输入 ```rb >> puts "A" if [] A => nil ``` 如果你看到的话,即使传递给`if`语句的数组为空,该语句也会打印 A。 这有点违背了最不令人惊讶的理论,但是请不要感到惊讶。 有一个书架,里面有书,所以如果你这样说 ```rb >> puts "Books Present" if ["treasure island", "I Love Ruby"] Books Present => nil ``` 它确实按预期方式打印 Books Present。 但是在这件事上 ```rb >> puts "Books Present" if [] Books Present => nil ``` 它仍然会打印有书本。 那是因为即使书架是空的,也有一个仍然是物体的书架。 因此,有些事情不是`nil`。 因此,它是`true`。 为确保其工作原理,请看下面的代码 ```rb >> nil.class => NilClass >> [].class => Array ``` 当我们查询什么是`nil`的类时,它表示其`NilClass`实际上是一个空东西。 但是,当我们查询空数组的类时,它仍然是`Array`,而不是`nil`或`false`,因此不是`true`。 检查必须执行的空数组 ```rb >> puts "A" unless [].empty? => nil >> puts "A" if [].first => nil ``` 在第一个中,`[].empty?`返回`true`,但是由于它在`unles`中,因此将无法执行依赖于它的语句。 如果看到第二个我们使用`[].first`,则返回`nil`。 在 irb 中尝试 ```rb >> [].first => nil ``` 因此,这也可以用于检查数组是否为空。 还是这样.....? ```rb >> a= [ nil, 1, 2, nil] => [nil, 1, 2, nil] >> puts "a is empty" unless a.first => a is empty >> puts "a is not empty" if a.first => nil >> puts "a is not empty" unless a.empty? a is not empty => nil ``` 不用考虑天气还是不使用`first`检查空度? ### 6.5。 压缩阵列 有时一个数组可能包含`nil`值,而你想删除它,在这种情况下,你可以在该数组上调用`compact`。 让我们尝试一个例子。 启动你的 irb 或 pry,然后输入以下内容 首先让我们初始化数组 ```rb >> a = [1, nil, 2, nil, 3, nil] => [1, nil, 2, nil, 3, nil] ``` 因此,在上面的语句中,我们使用三个`nil`值初始化了数组。 现在,如下所示通过压缩将`nil`值删除 ```rb >> a.compact => [1, 2, 3] ``` 凉! 因此,红宝石删除了`nil`值,例如魔术。 现在让我们看看`a`的样子 ```rb >> a => [1, nil, 2, nil, 3, nil] ``` 令我们沮丧的是,仍然保留了零值,真正发生了什么? 好吧,当你在`a`上调用 compact 时,将创建一个新的压缩数组,并将其返回给我们的 REPL <sup class="footnote">[ [24](#_footnotedef_24 "View footnote.") ]</sup> ,然后 REPL 将其打印出来。 那么如何使`a`真正改变呢? 如下所示,带有 bang 或`compact!`的简单调用紧凑型;) ```rb >> a.compact! => [1, 2, 3] >> a => [1, 2, 3] ``` ### 6.6。 转换数组值 Ruby 带有非常强大的数组操作,我们将看到如何在易于使用的命令中转换数组。 #### 6.6.1。 收藏 火起来你的撬或 irb 并输入以下内容 ```rb >> array = [1, 2, 3] => [1, 2, 3] >> array.collect{ |element| element * element } => [1, 4, 9] ``` 在上面的代码中,我们声明了类型为`Array`的变量`array`,在下一条语句中,我们在其上调用了名为`collect`的方法,并传递了此代码块`{ |element| element * element }`。 现在让我们看看它的作用。 调用`collect`时,首先创建一个返回数组。 在该块中,我们看到了一个名为`|element|`的东西,现在 collect 算法的工作原理如下。 首先,此数组具有值 1、2 和 3,因此此块运行 3 次。 在第一次运行期间,将 1 装入`element`,现在在块中我们指定了`element * element`,因此`1 * 1`为`1`,并将其压入返回数组。 现在返回数组为`[1]`。 现在,它取第二个值,即 2,并且发生相同的过程,现在返回数组为`[1, 4]`,类似地,返回数组最终变为`[1, 4, 9]`并返回。 `collect`不会修改调用它的对象,因此,如果你查看`array`是什么,它仍将与下面的显示相同 ```rb >> array => [1, 2, 3] ``` 你可以在 irb 中检查它。 如果要收集以修改被调用的对象,请使用爆炸符号,如下所示 ```rb >> array.collect!{ |element| element * element } => [1, 4, 9] >> array => [1, 4, 9] ``` #### 6.6.2。 keep_if 假设我们要在数组中具有匹配特定条件的元素,并想删除其他条件,我们可以使用`keep_if`函数,如下所示 ```rb >> array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >> array.keep_if{ |element| element % 2 == 0} => [2, 4, 6, 8, 10] ``` 我们上面有一个由十个元素组成的数组,并说我们要保持偶数或被 2 整除的元素,因此我们将其写为如下所示的语句 ```rb array.keep_if{ |element| element % 2 == 0} ``` 我们向`keep_if`传递了一个块。 其中,数组中的每个值都在`|element|`中捕获,并写入了条件`element % 2 == 0`,如果条件为 true,则该元素将保留在数组中,否则将其抛出。 `keep_if`修改了其调用的数组,与之不同的是,collect 返回新数组。 因此,如果在运行`keep_if`之后检查数组,其内容将发生更改。 #### 6.6.3。 delete_if 与`keep_if`相对,`delete_if`的作用恰好相反,下面显示了如果在 Array 对象上运行`delete_if`会发生什么。 ```rb >> array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >> array.delete_if{ |element| element % 2 == 0} => [1, 3, 5, 7, 9] >> array => [1, 3, 5, 7, 9] ``` ### 6.7。 阅读红宝石文档 毫无疑问,这本书不够全面,无法涵盖所有​​Ruby Array 库。 要了解更多信息,请在此处阅读 Ruby 文档 [https://ruby-doc.org/core-2.5.1/Array.html](https://ruby-doc.org/core-2.5.1/Array.html)