用ruby中字母表中的数字位置替换字符串中的字母
我试图创建一个方法,给定一个字符串,用它在字母表中的位置替换每个字母 如果文本中的任何内容不是一封信,我想忽略它,不返回它用ruby中字母表中的数字位置替换字符串中的字母,ruby,string,indexing,methods,replace,Ruby,String,Indexing,Methods,Replace,我试图创建一个方法,给定一个字符串,用它在字母表中的位置替换每个字母 如果文本中的任何内容不是一封信,我想忽略它,不返回它 "a" = 1, "b" = 2, etc. 范例 alphabet_position("The sunset sets at twelve o' clock.") 应返回“20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 23 5 12 22 5 15 3 12 3 11”(作为
"a" = 1, "b" = 2, etc.
范例
alphabet_position("The sunset sets at twelve o' clock.")
应返回“20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 23 5 12 22 5 15 3 12 3 11”
(作为字符串)
我试过这个,但没用:
def alphabet_position(text)
alph = ("a".."z").to_a
text = text.split(/./).map {|ch| if ch.in?(alph)
((alph.index[ch]).to_i+1).to_s
else
""
end
}.join(" ").strip
end
提前谢谢 要调试一段代码,请逐行运行它。很快你就会发现: 日落时间定在十二点 text.split(/。/)#=>[] 它不会做你认为它会做的事 我想你的意思是:
text.split('') #=> ["T", "h", "e", " ", ...
text.chars #=> ["T", "h", "e", " ", ...
还有几个错误,但我将留给您去解决。根据@Siim Liiser的答案,您也可以使用扫描方法获取字母
text = "The sunset sets at twelve o' clock."
irb(main):002:0> text.scan(/[a-z]/)
=> ["h", "e", "s", "u", "n", "s", "e", "t", "s", "e", "t", "s", "a", "t", "t", "w", "e", "l", "v", "e", "o", "c", "l", "o", "c", "k"]
如您所见,字母T为大写且缺失,要解决此问题,您可以在调用方法scan之前使用downcase:
irb(main):004:0> text.downcase.scan(/[a-z]/)
=> ["t", "h", "e", "s", "u", "n", "s", "e", "t", "s", "e", "t", "s", "a", "t", "t", "w", "e", "l", "v", "e", "o", "c", "l", "o", "c", "k"]
def字母表位置(文本)
text.downcase.split(“”).map do|字母|
索引=('a'..'z')。查找索引(字母)
索引+1如果索引
end.compact.join(“”)
结束
首先,我们可以构建转换,因为哈希查找非常快:
# alternatively letter_to_number = ('a'..'z').each.with_index(1).to_h
letter_to_number = ('a'..'z').zip(1..26).to_h
#=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5, "f"=>6,
# "g"=>7, "h"=>8, "i"=>9, "j"=>10, "k"=>11, "l"=>12,
# "m"=>13, "n"=>14, "o"=>15, "p"=>16, "q"=>17, "r"=>18,
# "s"=>19, "t"=>20, "u"=>21, "v"=>22, "w"=>23, "x"=>24, "y"=>25, "z"=>26}
然后简单地把它们换掉
# ruby >= 2.7
text.downcase.each_char.filter_map {|c| letter_to_number[c] }.join(' ')
# ruby < 2.7
text.downcase.each_char.map {|c| letter_to_number[c] }.compact.join(' ')
#=> "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11"
#ruby>=2.7
text.downcase.each_char.filter_map{| c | letter_to_number[c]}.join(“”)
#红宝石<2.7
text.downcase.each_char.map{c|letter_to_number[c]}.compact.join(“”)
#=> "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11"
女士们先生们,发动你们的引擎
def alphabet_position(text)
text.downcase.split('').map do |letter|
index = ('a'..'z').find_index(letter)
index + 1 if index
end.compact.join(' ')
end
您可能希望在循环之外构建
('a'..'z')
,这样就不会创建N个范围,其中N等于text.size。我不知道这是否非常重要,但您不需要对范围进行线性扫描以获得字母表中字符的偏移量,因为您可以减去ascii码。我不知道用ruby怎么做。另外,在第4行,零真值在ruby中吗?“a”可能有一个bug。不知道您是否尝试过它,但我发现果味gem在基准测试方面比内置的更好。对常量btw的调用很好,除了它比字母表位置
提供了不公平的优势,后者可以实现相同的功能。@engineersmnky,我已经使用了水果
很多次,在这里体验之后,我会回到它。最初我有效地使用了1.times{method(m).call(str)}
,从一次运行到下一次运行的结果遍布地图。定义一个常量似乎很公平,因为这种方法通常会被多次调用。我不理解你关于字母表位置的评论。我的意思是,正如我在帖子下评论的那样,范围(('a'..'z')
)可以在循环之外构造,在这种情况下,可以在方法本身之外构造(这是额外节省时间的地方,介于smnky\u pre\u 1\u 7
和smnky\u pre\u w\u常量之间)。这也是我喜欢的furty
,因为它是确定性的,你不必太在意跑步次数或跑步之间的个体差异。@engineersmnky,是的,但是find\u index
仍然是一个线性搜索,不是吗?对于furty-smnky\u pre\u 2\u 7\u,w\u常数类似于cary\u with\u arr;cary\u with\arr与cary相似;cary比smnky_pre_2_7快3倍±1.0;smnky_pre_2_7比tatiana快2倍±1.0;*repl.它仍在使用2.5.1,因此我不得不删除2.7选项。
convert "Sunset was at twelve o'clock, somewhere, on some day"
#=> "19 21 14 19 5 20 23 1 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11 19 15 13 5 23 8 5 18 5 15 14 19 15 13 5 4 1 25"
def alphabet_position(text)
text.downcase.split('').map do |letter|
index = ('a'..'z').find_index(letter)
index + 1 if index
end.compact.join(' ')
end
def smnky_1_7(str)
letter_to_number = ('a'..'z').zip(1..26).to_h
str.downcase.each_char.filter_map {|c| letter_to_number[c] }.join(' ')
end
def smnky_pre_1_7(str)
letter_to_number = ('a'..'z').zip(1..26).to_h
str.downcase.each_char.map {|c| letter_to_number[c] }.compact.join(' ')
end
LETTER_TO_NUMBER = ('a'..'z').zip(1..26).to_h
def smnky_pre_w_constant(str)
str.downcase.each_char.map {|c| LETTER_TO_NUMBER[c] }.compact.join(' ')
end
def convert_with_arr(str)
str.downcase.each_char.with_object([]) do |c,arr|
n = c.ord
arr << n - 96 if n.between?(97, 122)
end.join(' ')
end
str = "Sunset was at twelve o'clock, somewhere, on some day"
require 'benchmark'
def run(m, str)
500.times { method(m).call(str) }
end
Benchmark.bm(19) do |x|
x.report("Cary") { run(:convert, str) }
x.report("Tatiana") { run(:alphabet_position, str) }
x.report("smnky 1.7") { run(:smnky_1_7, str) }
x.report("smnky pre 1.7") { run(:smnky_1_7, str) }
x.report("smnky pre w/constant") { run(:smnky_pre_w_constant, str) }
x.report("Cary with arr") { run(:convert_with_arr, str) }
end
user system total real
Cary 0.018610 0.000300 0.018910 ( 0.019135)
Tatiana 0.067738 0.001138 0.068876 ( 0.070317)
smnky 1.7 0.028659 0.001035 0.029694 ( 0.030583)
smnky pre 1.7 0.032050 0.001662 0.033712 ( 0.035089)
smnky pre w/constant 0.013705 0.000323 0.014028 ( 0.014139)
Cary with arr 0.016989 0.000538 0.017527 ( 0.017925)