среда, 18 июня 2014 г.

Вывод правильного окончания слова в зависимости от числа

  Всем читателям блога привет! Сегодня снова делюсь опытом решения вставшей у меня на пути задачи - вывод правильного окончания слова в зависимости от идущего перед ним числа. И вновь задачу я решал на стороне сервера, то есть на PHP.

Прежде всего, немного о задаче

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

  Переписывать после каждой новой регистрации текст бессмысленно и глупо. Во-первых, потому что в сутки на проекте регистрируется по 10-13 специалистов «нужных» тексту профессий, а во-вторых, потому что на отслеживание новых участников требовалось бы много времени. Если такие маленькие задачки не автоматизировать на начальном этапе, проект просто-напросто перестанет быть интересным даже его владельцу.

  В этой связи была написана функция, которая возвращает массив с данными о имеющихся в базе профессиях. Так на -руках- странице у нас появились числа, простая подстановка которых время от времени давала результаты вида «12 программист», тогда как нам нужен был результат вида «12 программистов».

Принцип решения задачи

  Решение довольно банальное. Окончания профессий представляют собой 3 словоформы, одна из которых подходит для чисел 1, 21, 31 и так далее, вторая - для чисел 2, 3, 4, 22, 23, 24 и так далее, и третья - для чисел с 5 до 20 и двухзначных чисел, оканчивающихся на число от 5 до 0. Числа больше сотни повторяют тот же самый цикл, если отбросить от них все сотни и оставить лишь двухзначное число.

Решение задачи

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

Вызов функции и передача в неё нужных данных выглядит так:
wordEnding(12, array('программист', 'программиста', 'программистов'));
  Сначала мною была написана функция с использованием регулярных выражений. Выглядела она так:
function wordEnding($number, $words) {
    if (preg_match("#(11|12|13|14)$#", $number))
        $result = $words[2];
    else if (preg_match("#1$#", $number))
        $result = $words[0];
    else if (preg_match("#(2|3|4)$#", $number))
        $result = $words[1];
    else
        $result = $words[2];

    $result = "$number $responce";

    return $result;
}
  Этой функцией я и пользуюсь, так как работать с регулярными выражениями мне нравится. Однако стало интересно найти более оптимальное решение, в результате чего получилась такая функция:
function wordEnding($number, $words) {
    $numend = $number % 100;

    if ($numend >= 10 && $numend <= 20)
        $result = $words[2];
    else {
        $numend = $number % 10;
        if ($numend > 1 && $numend < 5)
            $result = $words[1];
        else if ($numend >= 5)
            $result = $words[2];
        else
            $result = $words[0];
    }

    $result = "$number $responce";

    return $result;
}
  Результатом работы при одинаковых исходных данных будет одна и та же связка «число название_профессии», но второй вариант работает в ~ 2,5 раза быстрее.

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

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

Отправить комментарий