【问题标题】:How do I use "slice_before" with initial_state in Ruby 1.9?如何在 Ruby 1.9 中将“slice_before”与 initial_state 一起使用?
【发布时间】:2012-07-19 00:08:53
【问题描述】:

我看到 Ruby 1.9 有一个新的枚举器,slice_beforeAPI docs 非常神秘。

尤其是我对采用 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 不接受Fixnum 作为初始值。为什么? Ruby 错误?。

我可以通过保留我自己的状态变量来解决这个问题,但这并不是我想要的漂亮的 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。

【问题讨论】:

    标签: ruby-1.9 ruby-1.9.3


    【解决方案1】:

    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 不起作用,因为它无法跟踪每个循环的状态。

    【讨论】:

    • 非常有趣。这并不直观。谢谢乔尔。你是怎么发现的?
    • 谁能解释这个代码示例中的第三行?为什么 Boolean &&'d 与(在我看来像)一个作业?
    • 是的。我更新了代码以使您更清楚。通常,“x && y”表示布尔值“和”。在 Ruby 中,“x && y”也可以表示“做 x,如果结果是真的,那么做 y”。类似地,“x || y”也可以表示“做x,如果结果是假的,那么做y”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2010-12-14
    • 2011-04-04
    • 2019-10-06
    相关资源
    最近更新 更多