在 rails 上增加 Ruby 中的字母字符串

Increment alphabetical string in Ruby on rails

我要解决的任务:

编写一个接受字符串的程序,将执行转换并 return 它。 对于参数字符串的每个字母,按字母顺序将其切换为下一个字母。 'z' 变为 'a','Z' 变为 'A'。案例不受影响。

def rotone(param_1)
  a = ""
param_1.each_char do |x|
    if x.count("a-zA-Z") > 0
        a << x.succ
    else
        a << x
    end
end
   a
end

我把这个:

Input:  "AkjhZ zLKIJz , 23y "
Expected Return Value: "BlkiA aMLJKa , 23z "
Return Value:          "BlkiAA aaMLJKaa , 23z "

当迭代器找到 'z' 或 'Z' 时,它递增两次 z -> aa 或 Z -> AA

input = "AkjhZ zLKIJz , 23y"

代码

p input.tr('a-yA-YzZ','b-zB-ZaA')

输出

"BlkiA aMLJKa , 23z"

您的问题是 String#succ (aka String#next) 的设计方式在接收器为 'z''Z':

时无法达到您的目的
'z'.succ #=> 'aa'
'Z'.succ #=> 'AA'

如果您将 a << x.succ 替换为 a << x.succ[0],您将获得所需的结果。


你可以考虑这样写。

def rotone(param_1)
  param_1.gsub(/./m) { |c| c.match?(/[a-z]/i) ? c.succ[0] : c }
end

String#gsub 的参数是匹配每个字符的正则表达式(因此每个字符都传递给 gsub 的块)1.

另见 String#match?。正则表达式 /[a-z]/i 匹配 字符 class [a-z] 中的每个字符。选项 i 匹配 case-independent,因此大写字母也匹配。


这是另一种编写方法的方法,该方法使用两个定义为常量的哈希值。

CODE = [*'a'..'z', *'A'..'Z'].each_with_object({}) do |c,h|
  h[c] = c.succ[0]
end.tap { |h| h.default_proc = proc { |_h,k| k } }
  #=> {"a"=>"b", "b"=>"c",..., "y"=>"z", "z"=>"a",
  #    "A"=>"B", "B"=>"C",..., "Y"=>"Z", "Z"=>"A"}
DECODE = CODE.invert.tap { |h| h.default_proc = proc { |_h,k| k } }
  #=> {"b"=>"a", "c"=>"b", ..., "z"=>"y", "a"=>"z",
  #    "B"=>"A", "C"=>"B", ..., "Z"=>"Y", "A"=>"Z"}

例如,

CODE['e'] #=> "f"
CODE['Z'] #=> "A"
CODE['?'] #=> "?"
DECODE['f'] #=> "e"
DECODE['A'] #=> "Z"
DECODE['?'] #=> "?"

让我们尝试使用 gsubCODEDECODE 以及示例字符串。

str = "The quick brown dog Zelda jumped over the lazy fox Arnie"

rts = str.gsub(/./m, CODE)
  #=> "Uif rvjdl cspxo eph Afmeb kvnqfe pwfs uif mbaz gpy Bsojf"
rts.gsub(/./m, DECODE)
  #=> "The quick brown dog Zelda jumped over the lazy fox Arnie"

请参阅 Hash#merge, Object#tap, Hash#default_proc=, Hash#invert and the form of Sting#gsub,它将散列作为其可选的第二个参数。

默认过程 添加到散列 h 会导致 h[k] 到 return k if h没有钥匙 k。如果 CODE 是在没有默认过程的情况下定义的,

CODE = [*'a'..'z', *'A'..'Z'].each_with_object({}) { |c,h| h[c] = c.succ[0] }
  #=> {"a"=>"b", "b"=>"c",..., "y"=>"z", "z"=>"a",
  #    "A"=>"B", "B"=>"C",..., "Y"=>"Z", "Z"=>"A"}

gsub 会跳过不是字母的字符:

rts = str.gsub(/./m, CODE)
  #=> "UifrvjdlcspxoephAfmebkvnqfepwfsuifmbazgpyBsojf"

如果没有默认过程,我们将不得不编写

rts = str.gsub(/./m) { |s| CODE.fetch(s, s) }
  #=> "Uif rvjdl cspxo eph Afmeb kvnqfe pwfs uif mbaz gpy Bsojf"

参见 Hash#fetch

1.正则表达式 /./ 匹配行终止符以外的所有字符。添加选项 m (/./m) 会导致 . 也匹配行终止符。