How do I use “slice_before” with initial_state in Ruby 1.9?

来源:互联网 发布:如何注销淘宝会员名 编辑:程序博客网 时间:2024/05/18 03:05

 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 > 3end.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 Fixnumfrom (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 = 0a.slice_before do |elem|  sum += elem  sum > 3 && sum = 0end.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_state is typically a state hash that stores key-value pairs.

To write your code using a state hash:

a.slice_before(sum: 0) do |elem, state|  state[:sum] += elem  state[:sum] > 3 && state[:sum] = 0end.to_a

The initial_state must respond to the #dup method, because it is duplicated on each loop.

The reason Fixnum doesn'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.


0 0
原创粉丝点击