0Pricing
Ruby Academy · 课时

包含 Enumerable

免费获得 map/select

包含 Enumerable 是 CoddyKit 上的免费 Ruby Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Ruby Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Ruby Academy 课程共包含 4 节课。

免费获得 map 和 select

类拥有 each 后,混入 Enumerable 就会立即获得 map、select、reduce、sort、min、max 等许多方法,而这些方法都建立在您的 each 之上。

class Bag
  include Enumerable
  def initialize(*x); @x = x; end
  def each; @x.each { |i| yield i }; end
end
p Bag.new(1, 2, 3).map { |n| n * 10 }

契约

规则很简单:包含 Enumerable 并定义 each。Enumerable 会在内部调用您的 each,以实现其他所有功能。

class Squares
  include Enumerable
  def initialize(n); @n = n; end
  def each
    (1..@n).each { |i| yield i * i }
  end
end
p Squares.new(5).to_a

使用 select 进行筛选

select 会保留代码块返回真值的元素。reject 则执行相反的操作。

class Nums
  include Enumerable
  def initialize(*x); @x = x; end
  def each; @x.each { |i| yield i }; end
end
n = Nums.new(1, 2, 3, 4, 5, 6)
p n.select(&:even?)
p n.reject(&:even?)

使用 reduce 进行聚合

reduce 会将集合折叠为单个值。

class Cart
  include Enumerable
  def initialize(*p); @p = p; end
  def each; @p.each { |i| yield i }; end
end
puts Cart.new(5, 10, 15).reduce(:+)

min、max 和 sort

只要您的元素具有可比较性,基于比较的方法就能正常工作。

class Scores
  include Enumerable
  def initialize(*n); @n = n; end
  def each; @n.each { |i| yield i }; end
end
s = Scores.new(7, 2, 9, 4)
puts s.min
puts s.max
p s.sort

find 和 include?

find 会返回第一个匹配的元素;include? 会检查成员关系。

class Words
  include Enumerable
  def initialize(*w); @w = w; end
  def each; @w.each { |x| yield x }; end
end
w = Words.new("cat", "dog", "bird")
puts w.find { |x| x.length == 4 }
puts w.include?("dog")

group_by 和 partition

Enumerable 提供了强大的分组辅助功能。

class Nums
  include Enumerable
  def initialize(*x); @x = x; end
  def each; @x.each { |i| yield i }; end
end
n = Nums.new(1, 2, 3, 4, 5)
p n.group_by(&:even?)
p n.partition(&:odd?)

排序需要可比较的元素

如果元素是自定义对象,请通过 Comparable 为它们提供 <=>,这样 sort、min 和 max 才知道如何排列它们。

Item = Struct.new(:price) do
  include Comparable
  def <=>(o); price <=> o.price; end
end
class Shelf
  include Enumerable
  def initialize(*i); @i = i; end
  def each; @i.each { |x| yield x }; end
end
shelf = Shelf.new(Item.new(30), Item.new(10), Item.new(20))
p shelf.min.price

带索引的迭代

Enumerable 还提供 each_with_index 和 each_with_object,用于进行更丰富的迭代。

class Letters
  include Enumerable
  def initialize(*l); @l = l; end
  def each; @l.each { |x| yield x }; end
end
Letters.new("a", "b", "c").each_with_index do |letter, i|
  puts "#{i}: #{letter}"
end

串联方法

由于这些方法会返回数组或枚举器,您可以将它们串联成清晰易懂的流水线。

class Nums
  include Enumerable
  def initialize(*x); @x = x; end
  def each; @x.each { |i| yield i }; end
end
result = Nums.new(1, 2, 3, 4, 5, 6).select(&:even?).map { |n| n * n }
p result

整合运用

包含 Enumerable 会带来巨大收益:

  • 只需定义一次 each。
  • 即可获得 map、select、reduce、sort、find、group_by 以及数十种其他功能。
  • 为元素添加 Comparable,以支持排序方法。
class Range5
  include Enumerable
  def each; (1..5).each { |n| yield n }; end
end
puts Range5.new.sum

快速检查

测试您对包含 Enumerable 的理解。

回顾

您学习了如何包含 Enumerable:

  • 定义 each,包含该模块,即可获得完整工具集。
  • map、select、reduce、find 和 group_by 都基于您的 each 运行。
  • 元素排序需要 <=>。
  • 方法可以串联成流水线。
class Tens
  include Enumerable
  def each; [10, 20, 30].each { |n| yield n }; end
end
p Tens.new.map { |n| n + 1 }

常见问题解答

「包含 Enumerable」课时是免费的吗?

是的 — 「包含 Enumerable」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Ruby Academy 课程的其余内容,请升级到 CoddyKit PRO。 Ruby Academy 课程共包含 4 节课。

「包含 Enumerable」这节课中我会学到什么?

免费获得 map/select 你通过在浏览器中直接运行的动手代码来练习 Ruby Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Ruby Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Ruby Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「包含 Enumerable」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Ruby Academy 课中编写并运行代码吗?

能。每节 Ruby Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 编写自定义 each
  2. 包含 Enumerable
  3. 惰性枚举器
  4. 枚举器对象
← 返回 Ruby Academy