Ruby Enumerable

Enumerable 模块提供了许多有用的方法来处理集合,例如 数组哈希范围

任何包含 Enumerable 的对象意味着您可以轻松地遍历该集合中的每个项目,并使用 mapselectfind 等有用方法。

例如,数组包含 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

常见问题

Enumerable 如何工作?

您已经看到了如何将 mapselectEnumerable 方法与数组一起使用。

在 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) 表现得像一个数字集合,从 110。我们使用 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 如此有用的几个原因

  • 通过消除手动编写循环的需要来节省时间。
  • 使您的代码更短、更清晰、更易于理解。
  • 为各种数据任务提供灵活而强大的工具。
  • 可与数组、哈希、范围甚至您的自定义集合无缝协作。

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战