问题
我想解析文本框的行,以便从中生成项目。
我已经开始工作,但它看起来很丑陋。
如何清理“if / else”一塌糊涂?
代码
class LineParser
def self.parse(line)
line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
return matches_to_hash(line_matches)
end
def self.matches_to_hash(matches)
hash = {}
keys = [:name, :price, :description_text, :quantity, :cat1]
keys.each do |key|
if key == :price
hash[key] = matches[key].to_f
elsif key == :quantity
if matches[key].nil?
hash[key] = 1
else
hash[key] = matches[key].to_i
end
else
hash[key] = matches[key]
end
end
hash
end
end
答案 0 :(得分:4)
此
if matches[key].nil?
hash[key] = 1
else
hash[key] = matches[key].to_i
end
相当于
hash[key] = (matches[key] || 1).to_i
对于具有多个分支的if / else链,也许case语句更合适。
答案 1 :(得分:3)
从解析中删除了显式返回。
class LineParser
def self.parse(line)
line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
matches_to_hash(line_matches)
end
def self.matches_to_hash(matches)
{
:price => matches[:price].to_f,
:quantity => (matches[:quantity] || 1).to_i,
:name => matches[:name],
:description_text => matches[:description_text],
:cat1 => matches[:cat1]
}
end
end
答案 2 :(得分:2)
要整理matches_to_hash,我会这样做:
def self.matches_to_hash(matches)
hash = {}
hash[:name] = matches[:name]
hash[:price] = matches[:price].to_f
hash[:description_text] = matches[:description_text]
hash[:quantity] = matches[:quantity].nil? ? 1 : matches[:quantity].to_i
hash[:cat1] = matches[:cat1]
hash
end
但是,我想我只会将解析改为:
def self.parse(line)
line_matches = line.chomp.match(/([[:print:]]+) \$(\d+\.*\d*)( +?([^\+#]([[:print:]][^\+#])*))?( +?(\+(\d+)))?( +?#([[:print:]][^#]*))?$/)
hash = {}
hash[:name] = $1
hash[:price] = $2.to_f
hash[:description_text] = $3
hash[:quantity] = $4.nil? ? 1 : $4.to_i
hash[:cat1] = $5
hash
end
答案 3 :(得分:1)
class LineParser
def self.parse(line)
line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
return matches_to_hash(line_matches)
end
def self.matches_to_hash(matches)
hash = {}
[:name, :price, :description_text, :quantity, :cat1].each do |key|
case key
when :price
hash[key] = matches[key].to_f
when :quantity
hash[key] = 1 if matches[key].nil?
hash[key] = matches[key].to_i unless matches[key].nil?
else
hash[key] = matches[key]
end
hash
end
end
答案 4 :(得分:1)
我不完全确定当每个键执行不同的操作时,为什么要循环键。为什么不一个一个地处理它们呢?
class LineParser
def self.parse(line)
line_matches = line.chomp.match(/(?<name>[[:print:]]+) \$(?<price>\d+\.*\d*)( +?(?<description_text>[^\+#]([[:print:]][^\+#])*))?( +?(\+(?<quantity>\d+)))?( +?#(?<cat1>[[:print:]][^#]*))?$/)
return matches_to_hash(line_matches)
end
def self.matches_to_hash(matches)
hash = {}
hash[:price] = matches[:price].to_f
hash[:quantity] = (matches[:quantity] || 1).to_i
hash[:name] = matches[:name]
hash[:description_text] = matches[:description_text]
hash[:cat1] = matches[:cat1]
hash
end
end
注意:我也偷了Thilo发布的关于数量的聪明一点。