2013-06-19 3 views
4

Я писал код, и это оказалось слишком уродливым по своему вкусу. В любом случае, я могу реорганизовать его так, чтобы я не использовал вложенные операторы if?Ruby: inested if statements

def hours_occupied(date) 
    #assuming date is a valid date object  
    availability = get_work_hours(date) 
    focus = "work" 

    if availability.nil 
    availability = get_family_hours(date) 
    focus = "family" 

    if availability.nil 
     availability = get_friend_hours(date) 
     focus = "friends" 
    end 
    end 
end 

Я знаю, что я буду в состоянии сделать что-то вроде этого дост

availability = get_work_hours(date) || get_family_hours(date) || get_friend_hours(date) 

но как установить переменную фокусировки соответственно?

+3

Можем ли мы предположить, что вы не показываете полный метод? в противном случае нет смысла назначать эти неиспользуемые переменные. Если это так, добавьте «...» в качестве заполнителя в нижней части метода. – tokland

+1

@tokland: Я не могу полностью понять предмет и цель его кода, что делает меня неспособным ответить. –

ответ

1

Еще один способ, это просто переназначить значения, если есть необходимость:

def hours_occupied(date) 
    availability, focus = get_work_hours(date), "work" 
    availability, focus = get_family_hours(date), "family" unless availability 
    availability, focus = get_friend_hours(date), "friend" unless availability 
end 

или с использованием итератора:

def hours_occupied(date) 
    availability = focus = nil 
    %w(work family friend).each {|type| availability, focus = self.send(:"get_#{type}_hours", date), type unless availability} 
end 
5

Я хотел бы сделать что-то вроде следующего, как это ясно показывает, что каждый случай взаимоисключающими:

def hours_occupied(date) 
    if availability = get_work_hours(date) 
    focus = "work" 
    elsif availability = get_family_hours(date) 
    focus = "family" 
    elsif availability = get_friend_hours(date) 
    focus = "friends" 
    end 
end 
+2

Условные обозначения Ruby являются выражением, поэтому нет необходимости повторять 'focus' 3 раза – tokland

3

Я бы написать:

def hours_occupied(date) 
    focus = if (availability = get_work_hours(date)) 
    "work" 
    elsif (availability = get_family_hours(date)) 
    "family" 
    elsif (availability = get_friend_hours(date)) 
    "friends" 
    end 
    # I guess there is more code here that uses availability and focus. 
end 

Однако, я не уверен, имеющие разные методы для разных типов - хорошая идея, это делает код сложнее писать. Другой подход с использованием Enumerable#map_detect:

focus, availability = [:work, :family, :friends].map_detect do |type| 
    availability = get_hours(date, type) 
    availability ? [type, availability] : nil 
end 
+0

Мне никогда не нравятся видения назначений внутри условного теста. Это слишком похоже на C или Perl и дает мне кошмары. Большое спасибо. :-) –

+0

@theTinMan: Добро пожаловать :-) Некоторые люди скажут, что если язык позволяет это (например, Python не делает), зачем его избегать? не можете ли вы сказать == из a =? Но я не буду :-) Мне нравится эта конструкция, потому что она упрощает код с меньшими вложенными выражениями. Обратите внимание, что парнеры делают его более заметным. – tokland

1

случай, когда также вариант:

focus = case availability 
when get_work_hours(date) 
    "work" 
when get_family_hours(date) 
    "family" 
when get_friend_hours(date) 
    "friends" 
end 
+0

либо это неправильно, либо 'case' работает иначе, чем я думал :-) – tokland

+0

@Tokland Пример с фиктивными данными [здесь] (http://ideone.com/70t9oY) – steenslag

+1

, но' availability' должен содержать первый не-нуль * результат * вызова метода, это неизвестно заранее. – tokland

 Смежные вопросы

  • Нет связанных вопросов^_^