4

我看到 Ruby 1.9 有一个新的枚举器,slice_before. API 文档非常神秘。

特别是我对initial_state取值的变化感到困惑。

例如,每当元素的累进总和超过某个值时,我想将带有数字的数组拆分为子数组:

a = [1,2,0,1,2,3]
a.slice_before(0) do |elem, sum|
  sum += elem
  sum > 3
end.to_a

预期输出:

[[1,2,0], [1,2], [3]]

我认为总和就像一个“随身携带”或“备忘录”,inject但这似乎并没有成功。

此代码中的故障是一个神秘的错误:

TypeError: can't dup Fixnum
from (irb):43:in `each'

看起来slice_before不接受 aFixnum作为初始值。为什么?红宝石错误?

我可以通过保留我自己的状态变量来解决这个问题,但这并不是我想要的漂亮的 Ruby 语义。

sum = 0
a.slice_before do |elem|
  sum += elem
  sum > 3 && sum = 0
end.to_a

# => [[1, 2, 0], [1, 2], [3]]

那么是否initial_state可用于此目的?文档中的示例似乎主要是关于文本处理的。我正在使用 Ruby 1.9.3p194。

4

1 回答 1

5

initial_state通常是存储键值对的状态散列。

要使用状态哈希编写代码:

a.slice_before(sum: 0) do |elem, state|
  state[:sum] += elem
  if state[:sum] > 3
    # Reset the sum, so we'll get more elements
    state[:sum] = 0  
  end
end.to_a

initial_state必须响应该方法#dup,因为它在每个循环中都重复。

Fixnum不起作用的原因是因为它没有响应#dup. Fixnum 不起作用,因为它无法跟踪每个循环的状态。

于 2013-01-31T12:04:11.757 回答