当前位置 : 主页 > 编程语言 > ruby >

使用hash的Ruby音译

来源:互联网 收集:自由互联 发布时间:2021-06-23
我试着做Cyrillic =使用hash的拉丁音译,我使用#encoding:utf-8和 ruby 1.9.3.我希望此代码更改file_name的值.为什么这段代码会使file_name保持不变? abc = Hash.newabc = {"a" = "a", "b" = "б", "v" = "в", 'g'
我试着做Cyrillic =>使用hash的拉丁音译,我使用#encoding:utf-8和 ruby 1.9.3.我希望此代码更改file_name的值.为什么这段代码会使file_name保持不变?

abc = Hash.new
abc = {"a" => "a", "b" => "б", "v" => "в", 'g' => "г", 'd'=> "д", 'jo' => "ё", 'zh' => "ж", 'th' => "з", 'i' => "и", 'l' => "л", 'm' => "м", 'n' => "н",'p' => "п", 'r' => "р", 's' => "с", 't' => "т", 'u' => "у", 'f' => "ф", 'h' => "х", 'c' => "ц", 'ch' => "ч", 'sh' => "ш", 'sch' => "щ", 'y' => "ы",'u' => "ю", 'ja' => "я"} 
file_name.each_char do |c| 
     abc.each {|key, value| if c == value then c = key end }
end
.each_char的问题在于你的问题中的块变量-c没有指向字符串中允许在原位改变字符串的字符.有一些方法可以使每个字符的映射从那里开始工作(例如使用.map后跟.join) – 但与.tr相比它们效率低下!或.gsub!为了您的目的,因为将字符串分解为一个字符数组并重构它涉及创建许多Ruby对象.

我想你需要做点什么

file_name.tr!( 'aбвгдилмнпрстуфхцыю', 'abvgdilmnprstufhcyu' )

它非常有效地涵盖了单个字母的转换.然后你有一些多字母转换.我会用gsub!为此,以及您的哈希的反转副本

latin_of = {"ё"=>"jo", "ж"=>"zh", "з"=>"th", "ч"=>"ch", 
            "ш"=>"sh", "щ"=>"sch", "я"=>"ja"}
file_name.gsub!( /[ёжзчшщя]/ ) { |cyrillic| latin_of[ cyrillic ] }

注意,与each_char不同,.gsub中块的返回值!用于替换原始字符串中匹配的任何内容.上面的代码使用原始哈希的反转来快速找到匹配的西里尔字符的正确拉丁语替换.

你不需要tr! . . .相反,如果您愿意,只需使用第二种语法在一次传递中使用原始哈希的反转.使用两种方法的成本可能意味着你使用.tr!并没有真正获得那么多.但你应该知道String#tr!方法,它可以非常方便.

编辑:正如评论中所建议的那样.gsub!在这里可以为你做更多的事情.假设latin_of是带有西里尔字符键和拉丁语值的完整哈希,你可以这样做:

file_name.gsub!( Regexp.union(latin_of.keys), latin_of )

有两点需要注意:

> Regexp.union(latin_of.keys)正在获取要转换的键的数组,并确保gsub可以在String中找到它们以备替换> gsub!接受散列作为第二个参数,并通过将其作为关键字并将其替换为关联值来转换每个匹配 – 正是您要查找的行为.

网友评论