与返回 Enumerable 的 Ruby Enumerable.collect 等效吗?
在这段代码中,我创建了一个字符串“1”到“10000”的数组:
array_of_strings = (1..10000).collect {|i| String(i)}
Ruby Core API 是否提供了一种获取可枚举对象的方法,该对象允许我枚举同一列表,按需生成字符串值,而不是生成字符串数组?
这是一个进一步的示例,希望能够澄清我正在尝试做的事情:
def find_me_an_awesome_username
awesome_names = (1..1000000).xform {|i| "hacker_" + String(i) }
awesome_names.find {|n| not stackoverflow.userexists(n) }
end
其中 xform
是我正在寻找的方法。
Awesome_names 是一个 Enumerable,因此 xform 不会创建 100 万个元素的字符串数组,而只是根据需要生成并返回“hacker_[N]”形式的字符串。
顺便说一句,它在 C# 中可能如下所示:
var awesomeNames = from i in Range(1, 1000000) select "hacker_" + i;
var name = awesomeNames.First((n) => !stackoverflow.UserExists(n));
(一个解决方案)
这是 Enumerator 的扩展,添加了 xform 方法。它返回另一个枚举器,该枚举器迭代原始枚举器的值,并对其应用变换。
class Enumerator
def xform(&block)
Enumerator.new do |yielder|
self.each do |val|
yielder.yield block.call(val)
end
end
end
end
# this prints out even numbers from 2 to 10:
(1..10).each.xform {|i| i*2}.each {|i| puts i}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Ruby 2.0 引入了
Enumerable#lazy
< /a> 允许链接map
、select
等...,并且仅在最后使用to_a
生成最终结果,first
等...您可以通过require 'backports/2.0.0/enumerable/lazy'
在任何 Ruby 版本中使用它。否则,您可以使用
Enumerator.new { with_a_block }
。它是 Ruby 1.9 中的新增功能,因此如果您在 Ruby 1.8.x 中需要它,请require 'backports/1.9.1/enumerator/new'
。根据您的示例,以下内容不会创建中间数组,而只会构造所需的字符串:
如果需要,您甚至可以将 100000 替换为 1.0/0 (即无穷大)。
为了回答你的评论,如果你总是将你的价值观一对一地映射,你可能会得到类似的东西:
Ruby 2.0 introduced
Enumerable#lazy
which allows one to chainmap
,select
, etc..., and only generate the final results at the end withto_a
,first
, etc... You can use it in any Ruby version withrequire 'backports/2.0.0/enumerable/lazy'
.Otherwise, you can use
Enumerator.new { with_a_block }
. It's new in Ruby 1.9, sorequire 'backports/1.9.1/enumerator/new'
if you need it in Ruby 1.8.x.As per your example, the following will not create an intermediate array and will only construct the needed strings:
You can even replace the 100000 by 1.0/0 (i.e. Infinity), if you want.
To answer your comment, if you are always mapping your values one to one, you could have something like:
听起来您想要一个 Enumerator 对象,但不完全是。
也就是说,Enumerator 对象是一个可用于按需调用
next
的对象(而不是执行整个循环的each
)。 (许多人使用内部迭代器与外部迭代器的语言:each
是内部的,而枚举器是外部的。您驱动它。)枚举器可能看起来如下:
这里有一个链接,可详细讨论如何使用你可以在 Ruby 中懒惰地使用枚举器: http://www.michaelharrison.ws/weblog/? p=163
Pickaxe 书中也有专门的章节(Dave Thomas 的《Programming Ruby》)。
It sounds like you want an Enumerator object, but not exactly.
That is, an Enumerator object is an object that you can use to call
next
on demand (rather thaneach
which does the whole loop). (Many people use the language of internal versus external iterators:each
is internal, and an Enumerator is external. You drive it.)Here's how an enumerator might look:
Here's a link, to more discussion of how you might use Enumerators lazily in Ruby: http://www.michaelharrison.ws/weblog/?p=163
There's also a section on this in the Pickaxe book (Programming Ruby by Dave Thomas).
接下来要做的事情是在没有块的情况下调用时返回一个枚举器......
The next thing to do is to return an Enumerator when called without a block...
列表有一个each方法:
lists have an each method: