2015-09-17 6 views
1

Я написал следующий фрагмент кода Ruby, который используется для извлечения информации с html-страницы.Рефакторинг кода для удаления повторений регулярных выражений

combined = state = county = special = 0 

    unless options.nil? 

    unless /([0-9\.]+)% \(Combined\)/.match(options).nil? 
     combined = /([0-9\.]+)% \(Combined\)/.match(options)[1].to_f 
    end 

    unless /([0-9\.]+)% \(State\)/.match(options).nil? 
     state = /([0-9\.]+)% \(State\)/.match(options)[1].to_f 
    end 

    unless /([0-9\.]+)% \(County\)/.match(options).nil? 
     county = /([0-9\.]+)% \(County\)/.match(options)[1].to_f 
    end 

    unless /([0-9\.]+)% \(Special\)/.match(options).nil? 
     special = /([0-9\.]+)% \(Special\)/.match(options)[1].to_f 
    end 

    if combined==0 and state==0 and county==0 and special ==0 then 
     unless />([0-9\.]+)%</.match(options).nil? 
     combined = />([0-9\.]+)%</.match(options)[1].to_f 
     end   
    end 

    end 

Как отредактировать этот код, чтобы удалить повторение каждого регулярного выражения?

ответ

2
return if options.nil? 
options.scan(/([0-9.]+)% \(([\w]+)\)/) do 
    case $2 
    when "Combined".freeze then combined = $1.to_f 
    when "State".freeze then state = $1.to_f 
    when "County".freeze then county = $1.to_f 
    when "Special".freeze then special = $1.to_f 
    else 
    combined = $1.to_f if options =~ />([0-9.]+)%</ 
    end 
end 
+0

Опять же - отличный ответ. Могу ли я также спросить - почему вы используете .freeze в строках в матче? Я понимаю, что замораживание делает строку неизменной. Это победа в производительности? Или способ показать читателям, что эти строки являются константами? Или предотвратить модификацию? – madcow

+0

Это для исполнения. Без 'freeze' новый экземпляр строки будет генерироваться каждый раз, когда будет читаться эта часть кода, что является огромной тратой ресурсов. 'freeze' после строкового литерала обрабатывается специальным образом, так что он генерируется только один раз. – sawa

+0

@madcow Почему вы удалили свой ответ? Ваш код был чистым и дал правильные результаты. – Alik

2

Update: То же подход, но очистке кода немного

results = Hash.new(0) 
if options 
    %w(Combined State County Special).each do |query| 
    options =~ /([0-9\.]+)% \(#{query}\)/ 
    results[query.downcase.intern] = $1.to_f if $~ 
    end 

    if results.values.all?(&:zero?) 
    options =~ />([0-9\.]+)%</ 
    results[:combined] = $1.to_f if $~ 
    end 
end 
Смежные вопросы