Каков наилучший подход к реализации этого алгоритма?

#algorithm #optimization

#алгоритм #оптимизация

Вопрос:

Какой был бы наилучший способ написать алгоритм, подобный:

 if (a) {
  doA();
  done();
}
else if (b) {
  doB();
  done();
}
else if (c) {
  doC();
  done();
}
  

другой подход, который я подумал:

 done = true;
if (a) {
  doA();
}
else if (b) {
  doB();
}
else if (c) {
  doC();
}
else {
  done = false;
}
if (done) {
  done();
}
  

Что лучше? Есть ли другой наилучший подход?

Комментарии:

1. Использование switch инструкции или даже лучших функций полиморфного / перегруженного языка кажется правильным решением.

Ответ №1:

Без какого-либо контекста наиболее естественным способом для меня является:

 bool do_it(int condition)
{
    switch (condition)
    {
        case a: doA(); return true;
        case b: doB(); return true;
        case c: doC(); return true;
        default: return false;
    }
}

// ...

if (do_it) done();
  

поскольку он абстрагирует логику «если все это удастся, тогда выполняйте call done() «.

Но есть много других способов сделать это. Особенно, если количество условий, вероятно, будет расти в будущем, я бы вообще этого не делал.

Ответ №2:

Зависит от того, сколько существует условий / действий и какой язык вы используете.

ООП и полиморфизм могли бы прекрасно работать.

Ответ №3:

Используйте switch инструкцию, попутно устанавливая isDone флаг, и вызывайте done() на основе флага.

Комментарии:

1. Я не думаю, что switch будет работать с другими условиями. В некоторых языках.

2. Особенно в c-подобных языках switch можно использовать только для сравнения одной переменной с несколькими возможными значениями. Никаких сложных условий.

3. Ничто в его примере не заставляет меня думать, что переключатель не сработает. Если он не может использовать переключатель, тогда все в порядке, это было просто предложение, я не говорю, что это ЕДИНСТВЕННЫЙ способ сделать это?

Ответ №4:

Если a, b и c — разные сложные условные выражения, то ваше первое решение является лучшим. Возможно, вы можете избежать элементов «else if», если этот код находится внутри функции, вот так:

 private void doit() {
    if (a) {
        doA();
        done();
        return;
    }
    if (b) {
        doB();
        done();
        return;
    }
    if (c) {
        doC();
        done();
        return;
    }
}
  

Так что для меня это скорее вопрос стиля кода.

Ответ №5:

Я бы написал это как

 var failed = false;
if (a) doA();
else if (b) doB();
else if (c) doC();
else failed = true;
if (!failed) done();
  

Мне не нравится сначала присваивать переменной типа done значение true, а затем отменять его, потому что работа не выполняется до начала условного выполнения, поэтому это выглядит нелогично.

Мне также не нравится вариант switch case, потому что условия ‘a’, ‘b’, ‘c’ не обязательно являются взаимоисключающими; if … еще, если … в противном случае cascade поддерживает неисключительные условия, но switch() может отличаться в зависимости от языка. Например. вы не можете преобразовать каскадный if … еще можно переключиться на C .

Я думаю, что определенно важно удалить несколько точек вызова done(), потому что это избыточность, а затем проблема с обслуживанием, если done(), например, получает параметры.

Ответ №6:

Во-первых, используйте одну переменную условия, а не три. Во-вторых, я бы использовал карту указателей на функции с переменной условия в качестве ключа. Вот пример:

 #!/usr/bin/env python

def doA():
    pass
def doB():
    pass
def doC():
    pass
def done():
    pass

a = 3
b = 6
c = 8

doers = {}
doers[a] = doA
doers[b] = doB
doers[c] = doC
condition = a

# this is now the entire "algorithm":

if condition in doers:
    doers[condition]()
    done()