【问题标题】:How to pass unknown Proc recursively in Ruby如何在 Ruby 中递归传递未知 Proc
【发布时间】:2019-11-07 05:46:20
【问题描述】:

问题

我正在尝试编写一个方法 (Array#bubble_sort),它接受一个可选的 proc 参数。
当给定一个proc时,该方法应该根据proc对数组进行排序。
当没有给定proc时,该方法应该按递增顺序对数组进行排序。
递归地,这在不添加 proc 的情况下可以正常工作,但是当给定一个未知的 proc 时,我无法找到一种方法将其作为参数正确地传递回来。

代码

class Array
  def bubble_sort(&prc)

    prc = Proc.new{|a,b| a <=> b} if !prc

    self.each_with_index do |ele,idx|
      if prc.call(self[idx],self[idx+1]) == 1
        self[idx],self[idx+1] = self[idx+1], self[idx]
        self.bubble_sort(&prc) 
      end
    end

    self
    end
end

测试代码

[4, 12, 2, 8, 1, 14, 9, 25, 24, 81].bubble_sort返回[1, 2, 4, 8, 9, 12, 14, 24, 25, 81]的预期结果

[4, 12, 2, 8, 1, 14, 9, 25, 24, 81].bubble_sort { |a, b| a.to_s &lt;=&gt; b.to_s } 返回堆栈级别太深的错误,而不是[1, 12, 14, 2, 24, 25, 4, 8, 81, 9] 的预期结果

【问题讨论】:

  • 我不知道问题出在哪里,但是如果您传递一个与默认 proc 相同的 proc,它就可以工作。所以这与proc的内容有关,而不是自定义proc的传递
  • 哦,好的,我看到了差异。您的方法最终使用81, nil 调用proc。然而81 &lt;=&gt; nil == nil'81' &lt;=&gt; nil.to_s == 1。这种差异一定是导致无限循环的原因
  • 天哪,我花了很长时间才弄明白。谢谢!我通过在条件句末尾添加 t&amp;&amp; idx+1 != self.length 来修复。
  • 完美,无论如何我都会写一个答案来解释它
  • &amp;prcprc 转换为proc,但由于prc 已经是proc,&amp;prcprc 相同。我建议写bubble_sort!(prc = Proc.new{|a,b| a &lt;=&gt; b}),它给参数prc 一个默认值。我将bubble_sort 更改为bubble_sort!,因为您的代码修改了接收器。

标签: ruby algorithm recursion lambda proc


【解决方案1】:

问题不在于您传递了 proc,而在于 &lt;=&gt; 在数字和字符串上的工作方式不同。

当您的循环到达数组末尾时,self.idx 等于 self.length - 1 并且 self.idx + 1 等于 self.length。由于零索引,在数组上调用 self[self.length] 将始终为零。

所以,你最终打电话给proc.call(&lt;last element of array&gt;, nil)

太空飞船操作员的行为会有所不同,具体取决于您是使用 number &lt;=&gt; nil 还是 number.to_s &lt;=&gt; nil.to_s(这是您要比较的两个 proc 之间的差异):

81 <=> nil
# => nil

81.to_s <=> nil.to_s
# => 1

在您的情况下,您不希望与 nil 进行任何比较导致交换,因此您有两种选择:

  1. 如果第二个元素为 nil,您可以更改 proc 以返回 nil

    arr.bubble_sort do |a,b|
      b.nil? ? nil : a.to_s <=> b.to_s
    end
    
  2. 如果b 越界,您可以完全跳过比较:

    self.each_with_index do |ele,idx|
      next if idx + 1 == self.length
      # ... other stuff
    

【讨论】:

  • 也许 #3:self.each_index.each_cons(2) do |i1, i2| ....
猜你喜欢
  • 2023-03-19
  • 2014-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多