Какая структура данных лучше всего подходит для этой задачи? - PullRequest
0 голосов
/ 18 марта 2020

Посоветуйте, как лучше организовать этот код. Задача по существу проста: заданные A, B, C являются числовыми переменными. Между ними могут быть следующие отношения:
A> B> C
A

Также указана числовая переменная X. Эта переменная может быть равна A, B, C (3 варианта), может находиться в интервалах между ними (2 варианта) и go за пределами (быть меньше A или больше C (2 варианта) )). Всего 7 вариантов. Учитывая, что может быть как A> B> C, так и A Я решил эту проблему таким образом :

  if (X < A) { 
    // do something
  }
  if (X == A) {
    // do something else
  }
  if (X > A && X < B) {
    // another thing
  }
  // and so on..
}

Этот код работает, но он громоздок (куча if) и не очень читабелен (на самом деле имена переменных различаются, и кода больше). Как я могу организовать этот код по-другому? Можно ли выбрать структуру данных, которая сделает код более кратким и простым? Или по-другому описать условные проверки?

Ответы [ 3 ]

0 голосов
/ 18 марта 2020

Вы можете использовать концепцию механизмов правил.

  • Определите ваши правила (при условии, что A, B, C являются некоторыми константами)

    rules = [
            {
              "rule" : (X) => X > A,
              "action": (X) => { console.log("first rule passed")}
            },
            {
              "rule" : (X) => X == A,
              "action": (X) => { console.log("second rule passed")}
            },
            {
              "rule" : (X) => X > A && X < B,
              "action": (X) => { console.log("third rule passed")}
            }
            ..
    
       ];
    
  • Выполните ваши правила, как показано здесь.

rules.filter(r => r.rule(x)).forEach(r => r.action());

0 голосов
/ 18 марта 2020

Я не вижу, как вы можете уменьшить количество тестов, для которых вы должны кодировать, но вы можете улучшить время выполнения, внедрив простой двоичный поиск, который уменьшает количество тестов, которые вы на самом деле тестируете.

Если это всегда так, что один из A < B < C или A > B > C имеет значение true, тогда вы вдвое уменьшите число тестов простой проверкой, чтобы убедиться, что A < B. Затем вы можете уточнить это далее:

if (A < B)
{
    if (X < B)
    {
        if (X < A)
        {
            // do something
        }
        else if (X == A)
        {
            // do something
        }
        else // A < X < B
        {
            // do something
        }
    }
    else if (X < C)
    {
        if (X == B)
        {
            // do something
        }
        else // B > X < C
        {
            // do something
        }
    }
    else if (X == C)
    {
        // do something
    }
    else // X > C
    {
        // do something
    }
}
else  // A > B > C
{
    // similar logic as above
}

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

Вы можете устранить дублирующиеся логи c для случая A > B > C, написав функцию f(x, a, b, c), а для случая A > B > C вызовите ее с обратными параметрами A, B и C. После этого вам придется изменить возвращаемый результат, но это достаточно простое отображение.

0 голосов
/ 18 марта 2020

Я не вижу способа избавиться от 14 операторов if, но одно решение сделать его возможно более читабельным за счет сложности - это иметь функцию, которая принимает аргументы X, A, B и C и возвращает перечисление с одним из 14 элементов. Затем у вас есть оператор переключения для различных 14 задач.

Это может показать более ясное намерение с одной частью, идущей "вот 4 аргумента, сделайте из нее значение домена", а одна часть, идущая "здесь, является значением домена, сделайте некоторые вещи с ним ".

Немного похоже:

function react(driver, car, road, traffic){
  if( driver < car ) return action.increasevolume;
  if( car === traffic ) return action.speedup;
  if( ...
}

switch( react( driver, car, road, traffic  )) {
  case action.increasevolume:
    ...
  break;
  ...
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...