Таблицы поиска для повышения эффективности программирования


В этой статье мы рассмотрим, как можно улучшить программы, используя табличный поиск, а не длинные серии операторов if-else if. Разберем три примера на PHP, Python и JavaScript.

Решение с операторами if-else if

Давайте начнем с проблемы даты. Предположим, вам необходимо сопоставить месяц с количеством дней в этом месяце. Первое, что приходит в голову - это использовать много if-else if, которое присваивает дни определенному месяцу. Вот как это выглядит на PHP:

$month = 3;

if ($month == 1)
  $days = 31;
elseif ($month == 2)
  $days = 28;
elseif ($month == 3)
  $days = 31;
elseif ($month == 4)
  $days = 30;
elseif ($month == 5)
  $days = 31;
elseif ($month == 6)
  $days = 30;
elseif ($month == 7)
  $days = 31;
elseif ($month == 8)
  $days = 31;
elseif ($month == 9)
  $days = 30;
elseif ($month == 10)
  $days = 31;
elseif ($month == 11)
  $days = 30;
elseif ($month == 12)
  $days = 31;

echo $days;
Это очень длинная серия операторов.

Видно, что номера месяцев соответствуют индексам массива. С этим пониманием мы можем создать массив, который хранит дни каждого месяца, связывая дни в месяце с правильным индексом массива.

Вот инструкция по созданию этого списка:

$monthDays = [0,31,28,31,30,31,30,31,31,30,31,30,31];
Обратите внимание, что у нас есть 0 в первом элементе списка, так как мы не нумеруем месяцы, начинающиеся с 0. Другой способ сделать это - начать с январских дней, а затем вычесть 1 из числа, которое пользователь вводит за месяц.

Вот полная программа:

$monthDays = [0,31,28,31,30,31,30,31,31,30,31,30,31];
$month = 3;
$days = $monthDays[$month];
echo $days;
Мы сократили 26-строчную программу до четырех строк, сделав ее более читаемой и более эффективной.

Поскольку мы сделали это для дней в месяце, мы также можем сделать это для названий месяцев, чтобы наша программа могла ссылаться на месяц по его имени, а не только по его номеру. Вот модифицированная программа PHP, в которой есть список названий месяцев:

$monthDays = [0,31,28,31,30,31,30,31,31,30,31,30,31];
$monthNames = ["", "January", "February", "March", "April",
              "May", "June", "July", "August", "September",
              "October", "November", "December"];
$month = 3;
$days = $monthDays[$month];
$monthName = $monthNames[$month];

echo $days." in ".$monthName;


Давайте рассмотрим еще один способ решения этой проблемы в Python.

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

Вот словарное решение проблемы дней в месяце:

daysInMonth = {
  "January" : 31,
  "February" : 28,
  "March" : 31,
  "April" : 28,
  "May" : 31,
  "June" : 30,
  "July" : 31,
  "August" : 31,
  "September" : 30,
  "October" : 31,
  "November" : 30,
  "December" : 31}
month = input("What month is it? ")
days = daysInMonth[month]
print(month,"has",days,"days in it.")
То, что я создал в этих примерах, - это два типа таблиц поиска. Таблица поиска - это структура данных, в которой необходимые данные можно найти, обратившись либо к индексу (в случае массива или списка), либо к ключу (в случае словаря).

Пример булевой функции

Булева функция (функция, возвращающая логическое значение) может содержать таблицу поиска и использоваться вместо оператора if-else if. Однако сначала давайте рассмотрим пример, который не использует таблицу поиска в JavaScript.

Задача состоит в том, чтобы подсчитать количество гласных в строке. У вас может возникнуть соблазн проверить каждый символ строки с помощью оператора if-else if, например:

let sentence = "now is the time for all good people";
let count = 0;
for (let i = 0; i < sentence.length; i++) {
  if (sentence[i] == 'a' || sentence[i] == 'e' ||
      sentence[i] == 'i' || sentence[i] == 'o' ||
      sentence[i] == 'u') {
    count++;
  }
}
console.log("There are " + count + " vowels in the string.");
Но способ лучше - это хранить гласные в массиве, который затем проверяется, есть ли в нем указанный символ. Вот один из способов написания программы с помощью булевой функции:

function isVowel(ch) {
  let vowels = ['a','e','i','o','u'];
  if (vowels.includes(ch)) {
    return true;
  }
  return false;
}
let sentence = "now is the time for all good people";
let count = 0;
for (let i = 0; i < sentence.length; i++) {
  if (isVowel(sentence[i])) {
    count++;
  }
}
console.log("There are " + count + " vowels in the string.");
Одно из преимуществ этой программы по сравнению с предыдущей программой, которая использует оператор if-else if, заключается в том, что я использовал встроенную функцию массива JavaScript, includes. Использование встроенной функции более эффективно, чем перебор массива для сравнения каждого элемента с заданным символом, что заставило бы меня использовать if-else if в определении функции.

Использование таблицы поиска ступеней лестницы

Другой тип таблицы поиска - это таблица поиска ступеней лестницы. Данный тип таблицы используется, когда проблема не может быть решена с помощью “аккуратных” индексов массива или списка.

Предположим, что есть приложение для оценки, в котором вы должны присвоить буквенную оценку числовому баллу. Если диапазон числовых оценок нерегулярен, обычная таблица поиска не может быть использована.

Отсечки для оценок: 50 или ниже F; до 65,0 D; до 75,0 C; до 90,0 B; и до 100,0 A.

Вот программа:

let gradeRange = [50.0, 65.0, 75.0, 90.0, 100.0];
let grades = ["F", "D", "C", "B", "A"];
let maxGrade = grades.length - 1;
let studentScore = 68.7;
let gradeLevel = 0;
let studentGrade = "A";
while (studentGrade == "A" && gradeLevel < maxGrade) {
  if (studentScore < gradeRange[gradeLevel]) {
    studentGrade = grades[gradeLevel]
  }
  gradeLevel++;
}
console.log("A score of " + studentScore + " is a letter grade of " +
      studentGrade + ".");
Этот код работает путем циклического перебора диапазона оценок и сравнения числового балла студента с перечисленными верхними пределами в массиве gradeRange. Буквенная оценка определяется, когда оценка студента превышает верхнюю часть диапазона.

Попытка написать эту программу с использованием логики if-else if сделает код слишком сложным и может привести к логическим ошибкам. Еще одно преимущество использования этого типа таблиц, как и в предыдущих примерах, заключается в том, что использование таблицы поиска облегчает изменение диапазона, если это необходимо.

Преимущества таблиц поиска

Есть несколько преимуществ использования таблиц поиска по сравнению с логикой if-else if. Во-первых, код, использующий таблицы поиска, легче читать, особенно когда оператор if-else if длинный. Еще одно преимущество заключается в том, что таблицы поиска легче обновлять, если меняется логика. Попытка изменить сложное утверждение if-else if

Если вы обнаружите, что у вас возникли проблемы с логикой оператора if-else if, подумайте о том, чтобы изменить его на таблицу поиска.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, javascript, теория программирования, php, python




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.



Как парсить сайты с помощью CsQuery
Урок 2. Параллельный цикл for C#
Как запоминать карты при игре в дурака