可以通过调用某些方法而不传递块来创建Enumerator
对象,例如Array#reject:
(1..3).reject.to_a
# => [1, 2, 3]
这只是一些红宝石规则,更容易链接,还是有其他方法将行为传递给枚举器?
答案 0 :(得分:4)
这只是一些红宝石规则,更容易链接
是的,这个原因完全正确。轻松链接普查员。考虑这个例子:
ary = ['Alice', 'Bob', 'Eve']
records = ary.map.with_index do |item, idx|
{
id: idx,
name: item,
}
end
records # => [{:id=>0, :name=>"Alice"}, {:id=>1, :name=>"Bob"}, {:id=>2, :name=>"Eve"}]
map
会将每个元素都生成with_index
,这会将项目索引置于其顶部并生成块。阻止将值返回with_index
,返回map
(做其事,映射和)返回给调用者。
答案 1 :(得分:1)
这只是一些红宝石规则,更容易链接
这不是Ruby的规则。只是在没有块的情况下调用reject
方法(例如)返回Enumerator
。它可以做其他事情。
还是有其他方式将行为传递给
Enumerator
?
是的,Enumerator
封装了您创建Enumerator
的方法的行为。例如,从Enumerator
创建reject
会创建一个拒绝其某些元素的对象。 Enumerator
混合了Enumerable
,因此Enumerator
可以与其他任何Enumerable
进行混合。{1}}。例如:
enum = (1..3).reject
enum.with_index {|el, i| i.even? }
# => [2]
答案 2 :(得分:1)
正如@Sergio所说,它主要用于链接,但它超越了这一点。如果您有一个枚举器e
,则可以使用Enumerator#next和Enumerator#peek提取元素。以下是两个如何利用枚举器的例子。
问题:给定数组a
,构造另一个数组,如果i
为奇数且a[i]
,其索引i
的值为2*a[i]
1}}如果i
是偶数。假设a = [1,2,3,4]
。
人们通常会看到:
a.map.with_index { |n,i| n.odd? ? n : 2*n } #=> [1,4,3,8]
但也可以这样写:
e = [1,2].cycle #=> #<Enumerator: [1, 2]:cycle>
a.map { |n| e.next * n } #=> [1, 4, 3, 8]
问题:给定数组a
,块连续值等于数组。让我通过展示如何做到这一点来使这个陈述更加精确。假设a = [1,1,2,3,3,3,4]
。
a.chunk(&:itself).map(&:last) #=> [[1, 1], [2], [3, 3, 3], [4]]
在Ruby v2.2(#itself首次亮相)中,您可以使用Enumerable#slice_when:
a.slice_when { |f,l| f != l }.to_a
#=> [[1, 1], [2], [3, 3, 3], [4]]
但您也可以使用枚举器:
e = a.to_enum
#=> #<Enumerator: [1, 1, 2, 3, 3, 3, 4]:each>
b = [[]]
loop do
n = e.next
b[-1] << n
nxt = e.peek
b << [] if nxt != n
end
b
#=> [[1, 1], [2], [3, 3, 3], [4]]
请注意,当n
的最后一个值为e
时,e.peek
会引发StopInteration
例外。该异常由Kernel#loop通过突破循环来处理。
我并不是建议最后一种方法应该优先于我提到的其他两种方案,但还有其他情况可以有效地使用这种方法。
还有一件事:如果你有一个链式方法的表达式,你可以通过将枚举器转换为数组来检查其元素传递给块的枚举器的内容。从中可以看出需要哪些块变量。假设你想写:
[1,2,3,4].each_with_index.with_object({}) {....}
并在块中做了一些事情,但不确定如何表达块变量。你可以这样做:
e = [1,2,3,4].each_with_index.with_object({})
#=> #<Enumerator: #<Enumerator: [1, 2, 3, 4]:each_with_index>
:with_object({})>
e.to_a
#=> [[[1, 0], {}], [[2, 1], {}], [[3, 2], {}], [[4, 3], {}]]
这表明(比方说)传递给块的e
的第一个元素是:
[[1, 0], {}]
告诉使用块变量应该是:
(n,i), h = [[1, 0], {}]
n #=> 1
i #=> 0
h #=> {}
意味着应该写出表达式:
[1,2,3,4].each_with_index.with_object({}) { |(n,i),h|....}