1

有一个数组

a = 1, 2, 3, 4

和一个枚举器:

e = a.map!

然后,通过反复调用e.next,数组 a 被很好地销毁:

e.next #=> 1
a #=> [1, 2, 3, 4]
e.next #=> 2
a #=> [nil, 2, 3, 4]
e.next #=> 3
a #=> [nil, nil, 3, 4]

太搞笑了!但是当我尝试

e.next { |x| 2 * x } # => 4

我明白了

a #=> [nil, nil, nil, 4]

而不是想要的

a #=> [nil, nil, nil, 8]

我有什么误解?如何a.map!用元素做我想做的事?

我的问题是,我不完全理解枚举数。例如,使用前面的代码,枚举器e构成了一个后门a

e.each { 42 }
a #=> [42, 42, 42, 42]

我想知道,如何逐步使用 nil 以外的值来做到这一点。(我可以用 nils 逐渐填充它e.rewind几次e.next,如前所示。

4

3 回答 3

3

为了使map!行为如你所愿,你需要Enumerator#feed方法,考虑这个

ary = *1..4
enum = ary.map!
# the `loop` method handles `StopIteration` for us
loop do
  x = enum.next
  enum.feed(x * 2)
end

ary
# => [2, 4, 6, 8]
于 2013-06-13T08:34:27.627 回答
2

next从参考看来, Enumerator#next 似乎不接受一个块,所以这对你的调用没有影响。如果您只想在清除所有其他元素的同时将最后一个元素加倍,请执行类似的操作,考虑直接方法(例如a = a[0..-2].map!{|x| nil} + [a.last*2],也许更优雅)。无论如何,您能否为我们提供一个更详细的用例,以确保您正在做您真正需要的事情?

于 2013-06-06T22:53:22.993 回答
1

a.map!接受一个块,但如果没有提供块,则返回一个枚举器。Enumerator#next不接受块。

你想用它来实现你的目标:

a.map! {|x| x * 2}

如果要将数组中的所有元素乘以 2。

有关下一步的信息,请查看http://ruby-doc.org/core-2.0/Enumerator.html#method-i-next

如果您希望输出准确无误[nil, nil, nil, 8],您可以执行以下操作:

func = lambda { |x|
  unless x == 4
    nil
  else
    x * 2
  end
}

a.map!(&func) #> [nil, nil, nil, 8]
于 2013-06-06T22:45:30.697 回答