Enumerable 模块提供了许多有用的方法来处理集合,例如 数组、哈希和范围。
任何包含 Enumerable 的对象意味着您可以轻松地遍历该集合中的每个项目,并使用 map、select 和 find 等有用方法。
例如,数组包含 Enumerable,因此您可以使用这些方法来转换、过滤或搜索其元素。
让我们使用 map 方法(Enumerable 方法之一)将数组中的每个数字加倍
numbers = [1, 2, 3, 4, 5]
# Double each number
doubled = numbers.map { |n| n * 2 }
puts doubled
# Output: [2, 4, 6, 8, 10]
map 方法接受数组中的每个项目,并根据块内的代码对其进行更改。
这里,{ |n| n * 2 } 是您传递给 map 方法的代码块。
|n|代表数组中的每个项目。n * 2告诉 Ruby 如何通过将项目加倍来更改它。
常见的 Enumerable 方法
您已经在前面的示例中使用了 map 方法。除了 map 之外,其他一些常用的 Enumerable 方法在 Ruby 中处理集合时非常有用。
以下是一些最受欢迎的方法的快速概述
| 方法 | 描述 |
|---|---|
each |
逐个遍历每个项目。 |
select |
选择符合条件的项。 |
find |
查找符合条件的第一个项。 |
reduce |
将所有项合并为一个值。 |
each 方法
each 方法逐个遍历集合中的每个项目,并为每个项目执行代码。例如,
numbers = [1, 2, 3, 4, 5]
numbers.each { |n| p n }
# Print the numbers array
p numbers
输出
1 2 3 4 5 [1, 2, 3, 4, 5]
在此示例中,each 对数组中的每个数字执行代码块。p n 命令打印每个数字。
由于 each 不会更改原始集合,因此 numbers 数组保持不变。
select 方法
select 方法通过仅保留符合您指定的条件的项来过滤集合。例如,
numbers = [1, 2, 3, 4, 5]
evens = numbers.select { |n| n.even? }
p evens
输出
[2, 4]
在此示例中,select 方法遍历数组中的每个数字,并仅保留条件 n.even? 为 true 的数字。
find 方法
find 方法查找您提供的第一个符合条件的项。一旦找到,它就会停止搜索。
例如,
numbers = [1, 2, 3, 4, 5]
first_big = numbers.find { |n| n > 3 }
puts first_big
输出
4
在这里,find 方法返回第一个大于 3 的数字,即 4。
reduce 方法
reduce 方法通过重复应用您的块将集合中的所有项合并为一个值。例如,
numbers = [1, 2, 3, 4, 5]
sum = numbers.reduce(0) { |total, n| total + n }
puts sum
输出
15
在此示例中,reduce 方法将数组中的所有数字合并为一个值——总和 sum。
reduce(0) 中的 0 是计算的起始值(称为“初始累加器”)。
块 { |total, n| total + n } 接受两个参数
| 参数 | 描述 |
|---|---|
total |
在方法遍历数组时跟踪运行总计 |
n |
正在使用的数组中的当前数字 |
对于每个数字,它将 n 加到 total,逐步更新 sum。
遍历完所有数字后,reduce 方法将返回最终的 sum。
常见问题
您已经看到了如何将 map 或 select 等 Enumerable 方法与数组一起使用。
在 Ruby 中,要在集合上使用 Enumerable 方法,该集合的类必须定义 each 方法。这个 each 方法告诉 Ruby 如何逐个循环遍历项目。
例如,Array 类已经内置了 each 方法,这就是为什么您可以轻松地将 Enumerable 方法与数组一起使用。
但是,如果您创建自己的集合类怎么办?它默认没有 each 方法,因此您还不能在它上面使用 Enumerable 方法。
让我们定义自己的类,向其中添加 each 方法,然后尝试 Enumerable 方法
class MyCollection
include Enumerable # Bring in Enumerable methods
def initialize(items)
@items = items
end
def each
@items.each do |item|
yield item # Pass each item to the block
end
end
end
collection = MyCollection.new([1, 2, 3, 4, 5])
doubled = collection.map { |n| n * 2 }
p doubled
输出
[2, 4, 6, 8, 10]
在这里,我们在 MyCollection 类中定义了 each 方法。现在,我们可以将 Enumerable 方法(如 map)与我们的自定义集合一起使用。
将 Enumerable 与 Range 一起使用
您还可以对范围使用可枚举方法。例如,
# Define a range from 1 to 10
numbers = (1..10)
# Use select to pick only even numbers
evens = numbers.select { |n| n.even? }
p evens
输出
[2, 4, 6, 8, 10]
在这里,range (1..10) 表现得像一个数字集合,从 1 到 10。我们使用 select(一个 Enumerable 方法)来过滤并仅保留偶数。
将 Enumerable 与 Hash 一起使用
您还可以使用 Enumerable 方法(如 select)来过滤哈希中的键值对。例如,
# Define a hash of fruits with their quantities
fruits = { apple: 3, banana: 5, orange: 2, mango: 4 }
# Select fruits with quantity greater than 3
big_fruits = fruits.select { |fruit, qty| qty > 3 }
p big_fruits
输出
{banana: 5, mango: 4}
在这里,select 方法遍历每个键值对,并仅保留数量大于 3 的键值对。
为什么使用 Enumerable?
Enumerable 如此有用的几个原因
- 通过消除手动编写循环的需要来节省时间。
- 使您的代码更短、更清晰、更易于理解。
- 为各种数据任务提供灵活而强大的工具。
- 可与数组、哈希、范围甚至您的自定义集合无缝协作。