Ruby宏文本替换

时间:2014-10-24 15:39:46

标签: ruby text macros substitution

我知道Ruby中不可能使用宏,但是,我遇到了一个我不知道解决方法的情况。

我有两种方法(我可能有更多)几乎相同,只有几个变量名称不同。具体来说,我在外部和内部|n|循环中交换了|m|upto

def self.check_across
  0.upto(4) do |n|
    test = 0
    0.upto(4) { |m| if @@bingo_board[n][m] == "X" then test += 1 end }
    if test == 5 then return true end
  end
  return false
end

def self.check_down
  0.upto(4) do |m|
    test = 0
    0.upto(4) { |n| if @@bingo_board[n][m] == "X" then test += 1 end }
    if test == 5 then return true end
  end
  return false
end

在第一种方法中,我检查一个5x5宾果板,找到一排完整的" X"值,和第二个方法检查" X"的完整列。值。

我知道在SAS中你可以将这个方法包装在%macro中(如果你知道我的意思)。在Ruby中,我知道这不起作用,但我正在尝试做的是:

def self.check(x, y)
  0.upto(4) do |x|
    test = 0
    0.upto(4) { |y| if @@bingo_board[n][m] == "X" then test += 1 end }
    if test == 5 then return true end
  end
  return false
end

example.check(n, m)    # same as .check_across
example.check(m, n)    # same as .check_down

当然,这不起作用,因为nm将被视为存在于方法之外的变量名。

2 个答案:

答案 0 :(得分:2)

您可以使用块来完成类似的事情。

例如,

def check
  0.upto(4) do |i|
    test = 0
    0.upto(4) do |j|
      # hand control of how to deal with indices over to the calling method
      if yield(i,j) == 'X'
        test += 1
      end
    end
    return true if test == 5
  end
  false
end

def check_across(board)
  check do |i,j|
    # implementing logic for accessing rows
    board[i][j]
  end
end

def check_down(board)
  check do |i,j|
    # implementing logic for accessing columns
    board[j][i]
  end
end

快速健全检查:

a = [
%w(O O O O O),
%w(O O O O O),
%w(O O O O O),
%w(O O O O O),
%w(O O O O O)
]

b = [
%w(O O O O O),
%w(O O O O O),
%w(X X X X X),
%w(O O O O O),
%w(O O O O O)
]

c = [
%w(O O O X O),
%w(O O O X O),
%w(O O O X O),
%w(O O O X O),
%w(O O O X O)
]

check_across(a) #=> false
check_across(b) #=> true
check_across(c) #=> false

check_down(a) #=> false
check_down(b) #=> false
check_down(c) #=> true

答案 1 :(得分:1)

您可能想尝试这个未经测试的代码:

def self.check_across
  @@bingo_board.each do |n|
    return true if n.all?{ |m| m == 'X' }
  end

  false
end

def self.check_down
  @@bingo_board.transpose.each do |m|
    return true if m.all?{ |n| n == 'X' }
  end

  false
end

transpose是一个很好的方法,对这类问题很有用。 all?可以很容易地查看数组中的所有元素是否相同,如果相同则返回true。


看起来可能会被干掉:

def self.check_across
  @@bingo_board.any?{ |n|
    n.all?{ |m| m == 'X' }
  }
end

def self.check_down
  @@bingo_board.transpose.any?{ |m|
    m.all?{ |n| n == 'X' }
  }
end

any?有助于查找是否有任何元素与条件匹配并返回true。在这种情况下,行或列是否都是'X'。