首页 > 解决方案 > 在 Ruby 中将迭代器转换为数组的单行器

问题描述

这必须是一个常见问题解答,但经过大量网络搜索,我未能找到答案。我是 Ruby 编程语言的新手,所以我可能误解了一些基本的东西,或者我正在将我的 C#、F# 或 Haskell 知识投射到 Ruby 上。

如果我有类似以下的方法,是否有一种方法可以将其转换为数组或其他可变数据结构?

def foo
  yield 8
  yield 2
  yield 5
end

我知道我可以这样做:

ary = Array.new
foo { |x| ary << x }

然而,这不是单行的。例如,在 C# 中,我可以使用ToListToArray扩展方法,或者在 F# 中,例如Seq.toList

let foo = seq {
    yield 8
    yield 2
    yield 5
}

let arr = foo |> Seq.toList

Ruby 中是否有类似的单行代码?

还是我完全误解了 的本质foo

标签: ruby

解决方案


实际上,您的问题中有两个独立的问题。

第一个问题在标题中:

在 Ruby 中将迭代器转换为数组的单行器

这很简单:Enumerator,这是在 Ruby 中调用的迭代器,混合在 (inherits from)Enumerable中。Enumerable具有从 anEnumerable#to_a创建 an 的方法,因此也从 an创建,因为IS-ANArrayEnumerableEnumeratorEnumerator Enumerable

所以,如果你有一个Enumerator,你需要做的就是打电话to_a,例如

some_enum.to_a

但是,您没有Enumerator. 你有一个方法。所以,你没有问的真正问题是问题的关键,是:我如何Enumerator从方法创建一个?

这就是Object#enum_for

enum = enum_for(:foo)
#=> #<Enumerator: ...>

ary = enum.to_a
#=> [8, 2, 5]

但是请注意,在许多情况下,您实际上并不需要Array, 因为Enumerator继承自Enumerablelike Arraydoes,因此会响应许多相同的消息。

另请注意,按照惯例,Ruby 中的许多“迭代器”方法,例如Enumerable#map,#each等,Enumerator在没有块的情况下调用它们时将返回 an:

def foo
  return enum_for(__callee__) { 3 } unless block_given?

  yield 8
  yield 2
  yield 5
end

然后你可以简单地做:

enum = foo
#=> #<Enumerator: ...>

ary = enum.to_a
#=> [8, 2, 5]

推荐阅读