我要解决的任务:
编写一个程序,接受一个字符串,执行转换并返回它。对于参数字符串的每个字母,按字母顺序切换下一个字母。"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 ->a或Z ->AA
input = "AkjhZ zLKIJz , 23y"
代码p input.tr('a-yA-YzZ','b-zB-ZaA')
输出"BlkiA aMLJKa , 23z"
你的问题是字符串#succ(又名字符串#next)的设计方式不能满足你的目的,当收件人是'z'
或'Z'
:
'z'.succ #=> 'aa'
'Z'.succ #=> 'AA'
如果你用a << x.succ[0]
代替a << x.succ
,你会得到想要的结果。
你可以考虑这样写。
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
匹配字符类[a-z]
中的每个字符。选项i
使匹配与大小写无关的,因此也匹配大写字母。
这是另一种使用两个定义为常量的哈希值的方法。
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['?'] #=> "?"
让我们尝试使用gsub
,CODE
和DECODE
与示例字符串。
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和sting# gsub的形式,它将哈希值作为可选的第二个参数。
将默认进程添加到散列h
中,如果h
没有k
键,则h[k]
返回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"
看到散列#取回。
<一口>1。正则表达式/./
匹配除行结束符以外的所有字符。添加选项m
(/./m
)将导致.
也匹配行终止符。一口>