2013-01-08 14 views
-2

我正在解析简单的字符串输入,如:“Hello world!:-)”并将它们转换为一个数组,分割单词并可能做一些修改。我已经生成了以下可以工作的代码,但它似乎不是Ruby的惯用语。我该如何改进它?如何编写这个字符串解析更多的Ruby惯用语?

$mapping = Hash[ 
    "X" => "CODE_X", 
    "Y" => "CODE_Y", 
    "Z" => "CODE_Z", 
] 

def translate(input) 
    result = [] 
    tmp = "" 
    input.each_char do |c| 
    if $mapping.has_key?(c) 
     if result != "" 
     result << "normal " + tmp 
     tmp = "" 
     end 
     result << "special " + $mapping[c] 
    else 
     tmp += c 
    end 
    end 
    if tmp != "" 
    result << "normal " + tmp 
    end 
    return result 
end 

它似乎包含不必要的许多行,使其难以阅读。它是做什么的,也许一个例子有助于:

translate("HelloXworldYZ") => 
["normal Hello", "special CODE_X", "normal world", "special CODE_Y", "special CODE_Z"] 

或英文:解析字符串面向字符,并再次串连的字符。将它们作为“普通”+字符串添加到结果数组中,直到(1)没有更多字符或(2)有特殊字符(映射),它们将该字符串添加到数组中,并将特殊字符添加为“特殊” +映射并继续处理字符串的其余部分。

+0

你能描述简单的英语改造的探讨逻辑是什么? –

+0

@SergioTulentsev好吧,试了一下。看到我编辑的问题。 – Erandir

+0

它对我来说看起来不像普通的英语。 – sawa

回答

2
def translate(input,map) 
    input.split(/([#{Regexp.escape map.keys.join}])/).map do |part| 
    map.key?(part) ? "special #{map[part]}" : "normal #{part}" unless part.empty? 
    end.compact 
end 

p translate("HelloXworldYZ", 'X'=>'CODE_X', 'Y'=>'CODE_Y', 'Z'=>'CODE_Z') 
#=> ["normal Hello", "special CODE_X", "normal world", "special CODE_Y", "special CODE_Z"] 
+1

(跟上Jörg的;)如果你想在Y和Z之间有一个'空'的'正常',那么只需要'input.split(/( [#{Regexp.escape map.keys.join}])/)。map {| part | map.key?(部分)? “special#{map [part]}”:“normal#{part}”}' – Phrogz

2

如何

$mapping = { 'X' => 'CODE_X', 'Y' => 'CODE_Y', 'Z' => 'CODE_Z' } 

def translate(input) 
    input. 
    split(/([#{$mapping.keys.map(&Regexp.method(:escape)).join}])/). 
    each_slice(2). 
    map {|normal, special| [unless normal.empty? then "normal #{normal}" end, "special #{$mapping[special]}"] }. 
    map(&:compact). 
    flatten 
end 

translate("HelloXworldYZ") 
# => ["normal Hello", "special CODE_X", "normal world", "special CODE_Y", "special CODE_Z"] 

请注意,您的纯英文说明和测试用例不匹配。从简单的英文说明中,结果应该是["normal Hello", "special CODE_X", "normal world", "special CODE_Y", "normal", "special CODE_Z"]。在这种情况下,它是更简单:

$mapping = { 'X' => 'CODE_X', 'Y' => 'CODE_Y', 'Z' => 'CODE_Z' } 

def translate(input) 
    input. 
    split(/([#{$mapping.keys.map(&Regexp.method(:escape)).join}])/). 
    each_slice(2). 
    map {|normal, special| [['normal', unless normal.empty? then normal end].compact.join(' '), "special #{$mapping[special]}"] }. 
    flatten 
end 

translate("HelloXworldYZ") 
# => ["normal Hello", "special CODE_X", "normal world", "special CODE_Y", "normal", "special CODE_Z"] 

strscan库可能是更好的选择。

+1

+1提醒我Regexp.escape :) – Phrogz

0
$mapping = Hash[ 
    "x" => "CODE_X", 
    "y" => "CODE_Y", 
    "z" => "CODE_Z", 
] 

def translate(input) 
    $mapping.keys.each { |char| input.gsub!(char, "___#{char}___") } 
    array = input.split(/(___.___)/) 
    result = [] 

    array.each do |word| 
    if word.match /___.___/ 
     result << "special #{$mapping[word[3]]}" 
    else 
     result << "normal #{word}" unless word.empty? 
    end 
    end 
    result 
end 

translate("Helloxworldyz") 
#=> ["normal Hello", "special CODE_X", "normal world", "special CODE_Y", "special CODE_Z"] 
+1

看起来像下划线的整个标记东西不是必需的。至少我必须发布一个ascii正则表达式驴;) – doesterr