ruby1.9中的Iterators

本文介绍了Ruby 1.9中新增的ExternalIterators特性,对比内部迭代器,解释了如何使用ExternalIterators进行高效迭代,并提供了代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在ruby1.9中增加了External Iterators这中新的迭代类型,所有的Enumerable 都是External Iterators.而在ruby1.9之前的版本中的迭代都是internal iterator。

何为external iterator呢,其实我认为也就是一个生成器了:

iterator = 9.downto(1)             # An enumerator as external iterator
begin # So we can use rescue below
print iterator.next while true # Call the next method repeatedly
rescue StopIteration # When there are no more values
puts "...blastoff!" # An expected, nonexceptional condition
end



这里的Kernel.loop方法就是为了迭代External Iterators而专门创建的。当next方法到最后一个元素的时候,就会抛出StopIteration,因此这里我们捕捉这个异常来判断迭代是否结束.

任何External Iterators都可以调用rewind 方法来重启这个迭代器。要注意如果一个enumerator 基于像File这样的对象,那么调用rewind将不会起作用。

一旦一个External Iterators开始迭代,那么他就不能被clone和duplicated。

我们可以简单的使用External Iterators来创建一个each方法,也就是通过External Iterator来创建一个internal iterator:

module Iterable
include Enumerable # Define iterators on top of each
def each # And define each on top of next
loop { yield self.next }
end
end


下面我们可以这样做:

def iterate(iterator)
loop { yield iterator.next }
end

iterate(9.downto(1)) {|x| print x }



下面是三个函数,功能都是一样的,第一个使用internal iterators,第二个虽然使用了External iterators ,可是没有用loop方法,因此代码很丑陋,第三个方法是最好的方法。:

# Call the each method of each collection in turn.
# This is not a parallel iteration and does not require enumerators.
def sequence(*enumerables, &block)
enumerables.each do |enumerable|
enumerable.each(&block)
end
end

# Iterate the specified collections, interleaving their elements.
# This can't be done efficiently without external iterators.
# Note the use of the uncommon else clause in begin/rescue.
def interleave(*enumerables)
# Convert enumerable collections to an array of enumerators.
enumerators = enumerables.map {|e| e.to_enum }
# Loop until we don't have any more enumerators.
until enumerators.empty?
begin
e = enumerators.shift # Take the first enumerator
yield e.next # Get its next and pass to the block
rescue StopIteration # If no more elements, do nothing
else # If no exception occurred
enumerators << e # Put the enumerator back
end
end
end

# Iterate the specified collections, yielding tuples of values,
# one value from each of the collections. See also Enumerable.zip.
def bundle(*enumerables)
enumerators = enumerables.map {|e| e.to_enum }
loop { yield enumerators.map {|e| e.next} }
end

# Examples of how these iterator methods work
a,b,c = [1,2,3], 4..6, 'a'..'e'
sequence(a,b,c) {|x| print x} # prints "123456abcde"
interleave(a,b,c) {|x| print x} # prints "14a25b36cde"
bundle(a,b,c) {|x| print x} # '[1, 4, "a"][2, 5, "b"][3, 6, "c"]'


这里要注意,在ruby1.8中的zip效率很低,那是因为它首先转换参数为数组,然后迭代他,可是在1.9中,由于我们有了External Iterators,因此它的实现就是直接迭代。因此他就更高效.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值