2011-11-04 70 views
2

的問題如何清理此Ruby代碼?

我想分析的文本框的線條,以產生從中項目。

我有它的工作,但它看起來很醜陋。

如何清理「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

感謝大家的所有偉大的建議。我從一個問題中學到了很多東西! :) –

回答

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 
+0

該死的,真可愛。我討厭做整個散列= {}返回散列的事情,我知道一定是更好的方法。就是這個!謝謝。 –

+0

mmm紅寶石:) 如果您處於文字無意義的情況,您還可以使用對象#輕擊。 –

+0

P.S.帽子提示到@Thilo –

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語句更合適。

+0

我甚至沒有想到這一點。高超!謝謝。 –

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 
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 
+0

爲什麼要以PHP風格創建哈希? – tokland

+0

偉大的一點 - 我最初把這些匹配命名爲因爲它讓我像對象一樣的哈希,但是如果我在把它放入哈希之前需要對它進行操作,那麼沒有多少意義。 –

+0

@tokland:什麼是PHP風格? – drummondj

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發佈的關於數量的聰明點。

+0

看起來不錯,但不需要構建哈希更新它。只需一步即可構建散列。 – tokland

+0

是的,回頭看,我不知道爲什麼。我想我認爲這會減少重複並使代碼更簡單。男人,是我錯了!感謝您的優秀建議。 –