带有正则表达式匹配的Ruby case语句

时间:2012-03-20 19:00:36

标签: ruby regex switch-statement

我正在制作我的第二个红宝石计划,我坚持认为是我和完成的程序之间的最后一件事。我的任务是写一个Rock,Paper,Scissors方法来返回获胜的玩家。要做到这一点,它需要[[“Dave”,“S”],[“Dan”,“R”]]形式的游戏参数,其中“S”和“R”是“剪刀”和“摇滚”分别。然后它确定胜利者并返回包含获胜策略的数组。如果游戏长度错误或策略==或不在范围内,也会引发错误。

class WrongNumberOfPlayersError < StandardError ; end
class NoSuchStrategyError < StandardError ; end


def rps_game_winner(game)

raise WrongNumberOfPlayersError unless game.length == 2

  #Hash of whose Keys are the strategies and values are the players
  playr = {(game[0].slice(1).downcase) => game[0],
    (game[1].slice(1).downcase) => game[1]} #This fits on the above line in IRB

  #Collect Strategies in array for comparison
  stgys = playr.keys

  #raise NoSuchStrategyError unless players give strategies in range, no duplicates
  raise NoSuchStrategyError unless (stgys.select { |s| s.match /[prs]/ }.size == 2) 

  #determine Winner
  case stgys.to_s
   when /p/ && /r/
     playr["p"]
   when /p/ && /s/
     playr["s"]
   when /s/ && /r/
     playr["r"]
  end
end

这符合我的预期,检查针对正则表达式的策略并返回获胜者。除了最后一种情况,遇到的时候总是返回nil。如果我在其他任何一个之下调用播放器[“r”]成功,它将在“/ p /&amp;&amp; / r /”中返回正确的播放器。如果我改变顺序,它仍然不起作用,所以我知道它与它的位置没有关系。如果我在case语句之外进行单独的匹配调用,regex / r /将评估它应该何时进行。所以我相信我已经把它缩小到与/ s /和/ r /如何关联的事情,但否则我很难过。此外,任何有关DRYness的帮助表示赞赏,感谢您的帮助!

4 个答案:

答案 0 :(得分:0)

问题是您的/X/ && /X/格式。 Ruby不会将其解释为需要两个正则表达式匹配。我不确定哪一个,但我相信它会像when /p/, /r/一样对待它,如果 正则表达式匹配将是真的。当您测试game = [["Dave","S"], ["Dan","R"]]时,"r"与第一个案例陈述匹配,并且您尝试引用playr["p"]

请改为尝试:

case stgys.to_S
  when "pr", "rp"
    playr["p"]
  when "ps", "sp"
    playr["s"]
  when "sr", "rs"
    playr["r"]
end

答案 1 :(得分:0)

实际上你根本不需要case。 我的该任务解决方案版本:

def rps_game_winner(game)
  raise WrongNumberOfPlayersError unless game.length == 2
  raise NoSuchStrategyError if game.any? {|n| !(n[1] =~ /^[spr]$/i)}
  loose_hash = {'s' => 'r', 'p' => 's', 'r' => 'p'}
  strategy1 = game[0][1].downcase
  strategy2 = game[1][1].downcase
  loose_hash[strategy1] == strategy2 ? game[1] : game[0]
end

答案 2 :(得分:0)

您的问题是/p/ && /r/在实际用作标签之前已经过评估。由于这两者都不是假或零,/p/ && /r/等于/r/,并且类似于其他案例标签。

除非你为每个案例重写一个案例陈述,否则我认为case不适合你正在做的事情

答案 3 :(得分:0)

在问题说明的帮助下,我以不同的方式解决了问题。

def rps_game_winner(game)
  raise WrongNumberOfPlayersError unless game.length == 2
  raise NoSuchStrategyError unless game[0].length == 2 and game[1].length == 2
  raise NoSuchStrategyError unless game[0][1] =~ /^[RPS]$/ and game[1][1] =~ /^[RPS]$/
  return game[0] unless (game[0][1] == "P" and game[1][1] == "S") or
                        (game[0][1] == "S" and game[1][1] == "R") or
                        (game[0][1] == "R" and game[1][1] == "P")
  return game[1]
end

def rps_tournament_winner(tournament)
  return rps_game_winner(tournament) unless tournament[0][1] !~ /^[RPS]$/
  return rps_tournament_winner([rps_tournament_winner(tournament[0]), rps_tournament_winner(tournament[1])])
end

我已经测试了所有给定的场景,它对我有用。