循环方法,直到返回falsey

时间:2018-08-02 23:58:40

标签: ruby

我试图使气泡更短,然后我想到了

class Array
  def bubble_sort!(&block)
    block = Proc.new { |a, b| a <=> b } unless block_given?
    sorted = each_index.each_cons(2).none? do |i, next_i|
      if block.call(self[i], self[next_i]) == 1
        self[i], self[next_i] = self[next_i], self[i]
      end
    end until sorted
    self
  end

  def bubble_sort(&prc)
    self.dup.bubble_sort!(&prc)
  end
end

我不太喜欢sorted = --sort code-- until sorted上的东西。

我只想运行each_index.each_cons(s).none?代码,直到返回true。我使用until的情况很奇怪,但条件是我要运行的代码。无论如何,我的尝试似乎很尴尬,而红宝石通常有一种简洁的放置方法。有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

这只是我的意见

您是否曾经读过eachmap的ruby源代码以了解它们的作用

否,因为它们从方法名称中表达了明确的任务,并且如果您对其进行测试,则它们将获取一个对象,一些参数,然后向您返回一个值。

例如,如果我想测试String方法split()

s = "a new string"
s.split("new") 
=> ["a ", " string"]

您知道.split()是否接受block吗? 它是ruby的核心方法之一,但是要称它为90%的时间我都没有通过,我可以从名称.split()和返回值中了解它的作用

关注您正在使用的对象,方法应完成的任务及其返回值。

我阅读了您的代码,但无法对其进行重构,我几乎无法理解代码的作用。

我决定写下一些观点,并可能会跟进:

1)暂时不要使用proc,首先使面向对象的代码干净。

2)将bubble_sort!分为几种方法,每种方法都有明确的任务

def ordered_inverted!(bubble_sort!),def invert_values,可能执行invert_values until sorted,检查现有方法是否已执行此排序功能

3)编写这些方法的规范,tdd将促使您保持方法简单易测

4)如果这些方法不属于Array类,则将它们包括在适当的类中,有时过于复杂的方法仅在执行简单的String操作。

5)阅读有关重构的书籍实际上可能会有所帮助,然后在不必要时尝试强制使用proc和函数式编程。

答案 1 :(得分:1)

进一步研究之后,我确信最好的解决方案是

loop do
  break if condition
end

无论是那个问题还是我在问题中提出的方式,但我认为loop do版本更加清晰。

编辑:

哈,几周后,我解决了loop do解决方案后,我偶然发现了一个更好的解决方案。您可以将whileuntil循环与一个空块一起使用,如下所示:

while condition; end

until condition; end

所以问题中的气泡排序示例可以这样写

class Array
  def bubble_sort!(&block)
    block = Proc.new { |a, b| a <=> b } unless block_given?
    until (each_index.each_cons(2).none? do |i, next_i|
      if block.call(self[i], self[next_i]) == 1
        self[i], self[next_i] = self[next_i], self[i]
      end
    end); end
    self
  end

  def bubble_sort(&prc)
    self.dup.bubble_sort!(&prc)
  end
end