重构for循环ruby

时间:2017-05-03 04:48:51

标签: ruby algorithm refactoring tdd

我遇到了从共享for循环的两个方法重构一些重复代码的问题。具有重复代码的两个方法是gcdOfFiveUpToFive和remainderStepsUpToFive。这两个循环共享设置实例变量@m到5,两者在1..5循环中使用for x然后将@n设置为x以及它们都需要调用euclidGCD,尽管一个调用euclidGCD返回值和另一个将+ = 1添加到@count变量。我想要从一个方法返回2个值。我想我可以创建一个名为@countArray的第四个实例变量,并得到一个剩余步数的数组。

require 'minitest/autorun'


class GCDTest < Minitest::Test 
  def test_euclid_gcd
    gcdTestObject=GCD.new(20,5)
    assert gcdTestObject.euclidGcd==5
    assert gcdTestObject.gcdRemainderSteps==1

  end

  def test_euclid_two
    gcdTestObject=GCD.new(13,8)
    assert gcdTestObject.euclidGcd==1 
    assert gcdTestObject.gcdRemainderSteps==5
  end

  def test_euclid_loop
    gcdTestObject=GCD.new(0,0)
    assert gcdTestObject.gcdOfFiveUpToFive==[1,1,1,1,5]
  end 

  def test_count_of_loop
    gcdTestObject=GCD.new(0,0)
    assert gcdTestObject.remainderStepsUpToFive==[1,2,3,2,1]
  end


end



class GCD
  attr_accessor :m,:n
  attr_reader :count 
  def initialize(m,n)
    @m=m
    @n=n
    @count=0
  end

  def euclidGcd
    @count=1
    m=@m 
    n=@n
    r= m % n
    until r==0 
      m=n
      n=r
      r= m % n
      @count+=1
    end
    return n  
  end

  def gcdRemainderSteps
    return @count
  end

  def gcdOfFiveUpToFive
    @m=5
    gcdArrayUpToFive=[]
    for x in 1..5
      @n=x
      gcdArrayUpToFive << euclidGcd
    end
    return gcdArrayUpToFive
  end

  def remainderStepsUpToFive
    @m=5
    gcdStepArrayUpToFive=[]
    for x in 1..5
      @n=x
      euclidGcd
      gcdStepArrayUpToFive << gcdRemainderSteps
    end
    return gcdStepArrayUpToFive
  end

  def fiveLoopExtraction

  end

1 个答案:

答案 0 :(得分:0)

重复的代码是:

array=[]
for x in 1..5
  # result = do something with x
  array << result
end
return array

这正是地图功能的作用 What does the "map" method do in Ruby?

Ruby方法名称应为snake_case。让我们重构一下,使用正确的命名约定和map函数。

 def gcd_of_five_up_to_five
    @m=5
    (1..5).map do |x|
      @n = x
      # in ruby you don't have to write return
      # value of last expression is returned automatically
      euclid_gcd
    end
  end

  def remainder_steps_up_to_five
    @m=5
    (1..5).map do |x|
      @n = x
      euclid_gcd
      gcd_remainder_steps
    end
  end

我用params调用它而不是使用@m和@n。这将简化代码。如果你将euclid_gcd更改为:def euclid_gcd(m:, n:),你会得到这个:

  def gcd_of_5_up_to_5
    (1..5).map { |x| euclid_gcd(m: 5, n: x) }
  end

  def remainder_steps_up_to_5
    (1..5).map do |x| 
      euclid_gcd(m: 5, n: x)
      gcd_remainder_steps
    end
  end

似乎这需要很少或不需要进一步重构。