【问题标题】:Take the last element of a lazy enumerator取惰性枚举器的最后一个元素
【发布时间】:2013-12-03 15:52:33
【问题描述】:

我有这样的功能:

(0..Float::INFINITY).lazy.take_while {|n|(n**2+ 1*n+41).prime?}.force[-1]

我将此用作优化练习。这很好用,但它的内存顺序为 O(n),因为它将创建整个数组,然后取最后一个元素。

我试图在不构建整个列表的情况下得到这个,因此是惰性枚举器。除了使用while 循环之外,我想不出任何办法。

(0..Float::INFINITY).lazy.take_while {|n|(n**2+ 1*n+41).prime?}.last.force

有没有办法以 O(1) 的空间顺序而不是 O(n) 的枚举数来做到这一点?

编辑:这里的示例不需要惰性,但我认为降低函数的空间复杂度可能更有用?

【问题讨论】:

  • 这与删除 lazyforce 有何不同? 39 双向。为什么1*n
  • 好点,在这种情况下懒惰不是必需的,因为我们使用的是 take_while,我只是习惯于在处理无穷大时使用它,即将编辑问题以反映这一点。
  • Err... 你已经在使用枚举器了,不是吗?
  • 是的,想在不建立列表的情况下这样做,现在问题中已经澄清了这一点。 :)
  • 请注意,实际构建数组可能有好处,具体取决于您真正在做什么:有了它,垃圾收集器不太可能在您处于中间状态时启动寻找价值。

标签: ruby optimization lazy-evaluation


【解决方案1】:

解决方案

使用注入来保持当前值,而不是构建数组。

(0..Float::INFINITY).lazy.take_while {|n|(n**2+ 1*n+41).prime?}.inject{|acc,n| n }

请注意,您必须使用lazy,否则inject 将构建一个中间数组。

验证

要查看如果不使用惰性会发生什么,请在重新启动 ruby​​ 并运行非惰性版本后运行以下命令。它将返回“看起来像”中间数组的数组。

ObjectSpace.enum_for(:each_object, Array).each_with_object([]) {|e, acc|
  acc << e if e.size == 40 and e.first == 0
}

非懒惰版本会返回:

[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]]

用lazy重新做测试会返回一个空数组。

【讨论】:

    【解决方案2】:

    如果你只是不想保存整个数组:

    (0..1.0/0).find {|n| !(n**2+n+41).prime?} - 1
    

    1.0/0Float::INFINITY 相同。我用它以防你没有看到它。据我所知,两者都不是可取的。

    我的第一个想法显然是矫枉过正:

    def do_it
      e = (0..1.0/0).to_enum
      loop do
        n = e.peek
        return e.inspect unless (n**2+n+41).prime?
        e.next
      end
    end
    
    do_it 
    

    【讨论】:

    • 正是我正在寻找的那种东西,我不知道 e.peek for enumerators
    • @Denis, [Enumerable#find](http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i-find) 返回表达式计算 true 的块中的第一个值 n(不是数组)。在这种情况下是40,但我们想要最后一个;因此-1。当你有这样的问题时,你应该养成检查文档和/或在 irb 中尝试的习惯。不是批评,而是建议。
    • 是的,这个编辑是我一直在寻找的东西(为什么我首先提出这个问题),我知道会有一个可以做我正在寻找的事情的枚举,我只是在文档中找不到,再次感谢!
    猜你喜欢
    • 2022-01-10
    • 2021-08-08
    • 2016-12-16
    • 1970-01-01
    • 2018-05-14
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多