如何编写更具Ruby风格的字符串解析?
我正在解析简单的字符串输入,比如:“helloworld!:-)”并将它们转换为一个数组,该数组将拆分单词并可能进行一些修改。我已经产生了下面的代码,它正在工作,但它似乎不是非常Ruby风格。我怎样才能改进它如何编写更具Ruby风格的字符串解析?,ruby,Ruby,我正在解析简单的字符串输入,比如:“helloworld!:-)”并将它们转换为一个数组,该数组将拆分单词并可能进行一些修改。我已经产生了下面的代码,它正在工作,但它似乎不是非常Ruby风格。我怎样才能改进它 $mapping = Hash[ "X" => "CODE_X", "Y" => "CODE_Y", "Z" => "CODE_Z", ] def translate(input) result = [] tmp = "" input.each_
$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
或者在英语中:按字符分析字符串并再次连接字符。将它们作为“普通”+字符串添加到结果数组中,直到(1)不再有字符或(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"]
请注意,您的简单英语描述和您的测试用例不匹配。根据您的简单英语描述,结果应该是[“正常你好”,“特殊代码X”,“正常世界”,“特殊代码Y”,“正常”,“特殊代码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库可能是更好的选择。$mapping=Hash[
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"]
“x”=>“代码x”,
“y”=>“代码y”,
“z”=>“代码”,
]
def翻译(输入)
$mapping.keys.each{char | input.gsub!(char,“{char}}
数组=输入.split(/(\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu)/)
结果=[]
数组。每个do |字|
如果word.match/\uuuu___/
结果你能用简单的英语描述转换逻辑吗?@SergioTulentsev好的,试过了。请看我编辑的问题。对我来说,它不像简单的英语。你应该考虑使用;它比一次只提取一个字符更有效,但允许您提取内容直到下一个匹配的正则表达式模式。您的纯英语描述和测试用例不匹配。根据你的简单英语描述,结果应该是[“正常你好”,“特殊代码X”,“正常世界”,“特殊代码Y”,“正常”,“特殊代码Z”]
。看起来不需要用下划线来标记整个标记。至少我发布了一个ascii正则表达式ass;)和(跟上Jörg;)如果你想在Y和Z之间有一个“空的”“正常”
,那么只需input.split(/([#{Regexp.escape map.keys.join}])/).map{part map.key?(part);“特殊的{map[part]}”:“正常的{part part}
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"]
$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"]