制作地图!调查员做我想做的事

时间:2013-06-06 22:18:13

标签: ruby

有一个数组

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以外的值。 (正如我之前所示,我可以使用e.rewinde.next多次逐渐填充nils。

3 个答案:

答案 0 :(得分: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]

答案 1 :(得分:2)

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

答案 2 :(得分: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]