I saw Ruby 1.9 has a new enumerator, slice_before. The API docs are pretty cryptic.
In particular I’m baffled by the variation that takes an initial_state value.
For example, I want to split an array with numbers into sub-arrays whenever the progressive sum of the elements exceeds some value:
a = [1,2,0,1,2,3]
a.slice_before(0) do |elem, sum|
sum += elem
sum > 3
end.to_a
Expected output:
[[1,2,0], [1,2], [3]]
I’m thinking the sum is like a “carry” or “memo” as in inject but that doesn’t seem to pan out.
The glitch in this code is a cryptic error:
TypeError: can't dup Fixnum
from (irb):43:in `each'
It looks like slice_before doesn’t accept a Fixnum as initial value. Why? Ruby bug?.
I can work around this by keeping my own state variable, but it’s not quite the beautiful Ruby semantic I was looking for.
sum = 0
a.slice_before do |elem|
sum += elem
sum > 3 && sum = 0
end.to_a
# => [[1, 2, 0], [1, 2], [3]]
So is initial_state usable for this purpose, or not? The examples in the docs seem to be mostly about text processing. I’m using Ruby 1.9.3p194.
The
initial_stateis typically a state hash that stores key-value pairs.To write your code using a state hash:
The
initial_statemust respond to the#dupmethod, because it is duplicated on each loop.The reason
Fixnumdoesn’t work is because it doesn’t respond to#dup. A Fixnum wouldn’t work because it can’t keep track of state on each loop.