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
如此有用的几个原因
- 通过消除手动编写循环的需要来节省时间。
- 使您的代码更短、更清晰、更易于理解。
- 为各种数据任务提供灵活而强大的工具。
- 可与数组、哈希、范围甚至您的自定义集合无缝协作。