@jejos

Как избавиться от множества if?

У меня есть задача, которую я решил, однако, не уверен что моё решение можно назвать хорошим. Суть такова:
есть 3 числовых переменных A, B, C. Каждая из них содержит число, они могут быть как равны между собой в разный момент времени, так и не равны друг другу. Также, в 1-й или более переменных значение может отсутствовать (null). Условия задачи выглядят так: "если A > B > C, то ответ считать по формуле A + B + C", или "если ((A == null) && (C > B), то ответ считать по другой формуле (B / C) * 2" и таких условий несколько штук. Я так и закодировал, и мое решение выглядит как несколько подряд идущих if'ов (10 штук), и внутри каждого if'а расписано по какой формуле считать ответ. Но честно говоря, оно мне не нравится. Мне оно видится как куча if'ов, составляющих громоздкую конструкцию, но я не вижу, как можно сделать это более читаемым и понятным. Не понимаю, как обернуть эти условия в понятные абстракции с названиями, чтобы это перестало быть похожим на кучу математических формул. Как можно сделать лучше?
Пример кода, о котором я говорю (и таких if 10 штук подряд):

if ((A < B) && (C > B)) {
value = (A + B) - 1
}
if ((A == null) && (C < B)) {
value = (C + B) * 2
}

PS: лучшее, что я пока смог придумать, это обернуть все эти вычисления в функцию, и дать поясняющие комментарии.
  • Вопрос задан
  • 3106 просмотров
Решения вопроса 2
saboteur_kiev
@saboteur_kiev
software engineer
Множество if это нормально.

Для оптимизации, надо смотреть вашу задачу целиком. Возможно не хватает опыта или внимания, чтобы найти закономерности, которые можно сократить. Но возможно что их и нет.
Если условия такие разные, что их нельзя сократить, значит будет десять if и магия тут не поможет.

Можете кинуть все условия, вдруг кто-то что-то найдет.
Ответ написан
Комментировать
Если нужно избежать копирования кода с проверкой значений переменных, можно написать функцию с именем типа getCaseId, которая будет получать на вход ваши переменные и возвращать строковый идентификатор (или константу с идентификатором), по которому вам будет понятно, какой из случаев в данный момент имеет место. Потом составьте блок switch и в нём для каждого идентификатора пропишите нужные математические действия.

Это может быть полезно, если у вас в нескольких местах кода есть зависимость от значений этих переменных — можно повторно вызывать функцию getCaseId, если нужно, и использовать эти идентификаторы.
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
uvelichitel
@uvelichitel
habrahabr.ru/users/uvelichitel
@asd111
Чтобы тебя больше не смущало большое количество if then else вот тебе пример кода из типичного лексера. Это не полный кусок и в нем больше 20 if then else и по другому писать особо нет смысла.
void next() {
        ...
        else if (token == '=') {
            // parse '==' and '='
            if (*src == '=') {
                src ++;
                token = Eq;
            } else {
                token = Assign;
            }
            return;
        }
        else if (token == '+') {
            // parse '+' and '++'
            if (*src == '+') {
                src ++;
                token = Inc;
            } else {
                token = Add;
            }
            return;
        }
        else if (token == '-') {
            // parse '-' and '--'
            if (*src == '-') {
                src ++;
                token = Dec;
            } else {
                token = Sub;
            }
            return;
        }
        else if (token == '!') {
            // parse '!='
            if (*src == '=') {
                src++;
                token = Ne;
            }
            return;
        }
        else if (token == '<') {
            // parse '<=', '<<' or '<'
            if (*src == '=') {
                src ++;
                token = Le;
            } else if (*src == '<') {
                src ++;
                token = Shl;
            } else {
                token = Lt;
            }
            return;
        }
        else if (token == '>') {
            // parse '>=', '>>' or '>'
            if (*src == '=') {
                src ++;
                token = Ge;
            } else if (*src == '>') {
                src ++;
                token = Shr;
            } else {
                token = Gt;
            }
            return;
        }
        else if (token == '|') {
            // parse '|' or '||'
            if (*src == '|') {
                src ++;
                token = Lor;
            } else {
                token = Or;
            }
            return;
        }
        else if (token == '&') {
            // parse '&' and '&&'
            if (*src == '&') {
                src ++;
                token = Lan;
            } else {
                token = And;
            }
            return;
        }
        else if (token == '^') {
            token = Xor;
            return;
        }
        else if (token == '%') {
            token = Mod;
            return;
        }
        else if (token == '*') {
            token = Mul;
            return;
        }
        else if (token == '[') {
            token = Brak;
            return;
        }
        else if (token == '?') {
            token = Cond;
            return;
        }
        else if (token == '~' || token == ';' || token == '{' || token == '}' || token == '(' || token == ')' || token == ']' || token == ',' || token == ':') {
            // directly return the character as token;
            return;
        }

        ...
}
Ответ написан
@Valera221
Делаю сайты
Можно сократить с помощью циклов for, while и массивов. Но желательно видеть как выглядит твой код.
Ответ написан
Комментировать
@zkrvndm
Софт для автоматизации
Вы можете загнать ваши условия в массив, используя Boolean, а затем красиво обработать все if внутри одного цикла for просто перебрав результирующий массив.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
SummerWeb Ярославль
от 120 000 до 180 000 ₽
КРАФТТЕК Санкт-Петербург
от 60 000 до 80 000 ₽
Brightdata Тель-Авив
от 5 500 до 6 500 $
15 июн. 2024, в 08:05
300 руб./в час
15 июн. 2024, в 07:59
300 руб./в час
15 июн. 2024, в 06:38
500 руб./за проект