Ruby:重构一个复杂的嵌套循环方法

时间:2011-12-07 12:38:33

标签: ruby refactoring iteration

我正试图摆脱代码中的重复。我有一个用棋子填充棋盘的方法:

def populate_checkers
  evens = [0, 2, 4, 6]
  odds  = [1, 3, 5, 7]

  0.upto(2) do |x_coord|
    if x_coord.even?
      evens.each do |y_coord|
        red_checker = Checker.new(x_coord, y_coord, :red)
        @board[x_coord][y_coord] = red_checker 
      end
    elsif x_coord.odd?
      odds.each do |y_coord|
        red_checker = Checker.new(x_coord, y_coord, :red)
        @board[x_coord][y_coord] = red_checker 
      end
    end
  end

  5.upto(7) do |x_coord|
    if x_coord.even?
      evens.each do |y_coord|
        black_checker = Checker.new(x_coord, y_coord, :black)
        @board[x_coord][y_coord] = black_checker 
      end
    elsif x_coord.odd?
      odds.each do |y_coord|
        black_checker = Checker.new(x_coord, y_coord, :black)
        @board[x_coord][y_coord] = black_checker 
      end
    end
  end
end

如何删除重复内容并仍能获得我需要的精确行为?

3 个答案:

答案 0 :(得分:3)

您可以尝试提取方法,然后将块提取到lambda中。然后你的代码将是可读的并且没有重复

def populate_checkers
  0.upto(2) do |x_coord|
    populate_checker(x_coord, :red)
  end

  5.upto(7) do |x_coord|
    populate_checker(x_cord, :black)
  end
end

def populate_checker(x_coord, color)
  evens = [0, 2, 4, 6]
  odds  = [1, 3, 5, 7]

  apply_checker = lambda do |y_coord|
   checker = Checker.new(x_coord, y_coord, color)
   @board[x_coord][y_coord] = checker
  end

  if x_coord.even?
    evens.each(&apply_checker)
  elsif x_coord.odd?
    odds.each(&apply_checker)
  end
end

答案 1 :(得分:2)

def populate_checkers
  evens = [0, 2, 4, 6]
  odds  = [1, 3, 5, 7]

  [0.upto(2), 5.upto(7)].each_with_index do |enum, i|
    enum.each do |x_coord|
      (x_coord.even? ? evens : odds).each do |y_coord|
        checker = Checker.new(x_coord, y_coord, i == 0 ? :red : :black)
        @board[x_coord][y_coord] = checker 
      end
    end
  end
end

可能有更好的方法来计算计数位,但这就是我得到的。

这是一个可能更好的解决方案......

def populate_checkers
  { :red => (0..2), :black => (5..7) }.each do |color, range|
    range.each do |x_coord|
      (x_coord.even? ? 0 : 1).step(7, 2) do |y_coord|
        checker = Checker.new(x_coord, y_coord, color)
        @board[x_coord][y_coord] = checker 
      end
    end
  end
end

答案 2 :(得分:1)

0.upto(2) do |x|
  0.upto(7) do |y|
    @board[x][y]=Checker.new(x, y, :red) if (x+y).even? 
  end
end

这只适用于红人。