Пятница , 26 Апрель 2024
ДомойПубликацииПравильное окончание слова или числа и слова с учётом морфологии

Правильное окончание слова или числа и слова с учётом морфологии

Доброго времени суток, уважаемые.

Если Вы программируете уже долгое время, наверняка встречались с задачей вывода правильного окончания слова с предшествующим ему числом. примером может служить хотя бы блог, точнее, показ количества комментариев. в простейшем случае это может выглядеть так: Комментариев — 1. а порой хочется так: 1 комментарий и так: 5 комментариев.

blogging

К сути: решение не для жжёных опытных перцев, а для тех, кто столкнулся с задачей впервые. привожу код для php. для javascript потребуется внести мизерные изменения (если лень делать даже это, смотрите исходники страницы).

Перед демонстрацией самой функции немного размышлений на заданную тему.

Если сравнить по данному сабжу русский и английский вариант, в последнем всё проще: существует один или больше одного. в русском же всё чуточку сложнее: один, несколько (2–4) и много (5 и выше). но и это ещё не всё! если попробовать посчитать хотя бы депутатов, получим следующее:

1 депутат
2–4 депутата
0, 5-9 или 10 депутатов

Попробуем эту схему для 30:

31 депутат
32–34 депутата
30, 35-39депутатов

Всё хорошо и красиво. но! есть небольше исключение:

11 депутатов
12 депутатов
13-19 депутатов

Начиная с 20 проблем уже нет: что заканчивается на 1 — один, на 2–4 — несколько, на остальные цифры — много. а всё, что выше сотни, соответствует по счёту первым десяткам.

Это важно. это поможет сформулировать основные критерии «построения» нужной функции:
1. Из любых чисел нас будут интересовать только 2 последних цифры;
2. Если число больше 10, но меньше 20, то применяем правило много. иначе для работы достаточно только последней цифры.


function get_correct_str($num, $str1, $str2, $str3) {
    $val = $num % 100;
    
    if ($val > 10 && $val < 20) return $num .' '. $str3;
    else {
        $val = $num % 10;
        if ($val == 1) return $num .' '. $str1;
        elseif ($val > 1 && $val < 5) return $num .' '. $str2;
        else return $num .' '. $str3;
    }
}


И, как обещал, небольшой пример, показывающий как это всё работает.

число:
текст для варианта «один»:
текст для варианта «несколько» (2–4)
текст для варианта «много»

Рейтинг: 0

Автор публикации

2 070
не в сети 12 месяцев

x64 (aka andi)

Комментарии: 2893Публикации: 405Регистрация: 02-04-2009
Так себеНеплохоХорошоЗамечательноСупер! (3 голосов, в среднем: 5,00 из 5)
Загрузка...

13 комментариев

  1. Спасибо что помогли smile

    Рейтинг: 0
  2. Юзай это. Проще меньше быстрее

    function om_number($number, $titles) {
    $cases = array (2, 0, 1, 1, 1, 2);
    return $number.» «.$titles[($number%100>4 && $number%100<20)? 2 : $cases[min($number%10, 5)]];
    }

    Рейтинг: 0
  3. VICTOR_81, спасибо, вариант хороший, оценил; изящно.
    но по тестам он быстрее не получился (php 5.2.13, разница составляет ~1.6 раза). да и проще его вряд ли можно назвать: множественные условия в одной строке заставляют немного подумать, прежде чем станет понятно, чего же, собственно, данный код делает.

    Рейтинг: 0
  4. Спасибо, лучшее что нашёл в поисковиках!

    Рейтинг: 0
  5. Только не кидайтесь камнями и не кройте (понятно чем)Вы тоже были маленькими. Блог на WordPress. Куда вставлять код?

    Рейтинг: 0
  6. 2Foxbat
    да хоть в код тем добавляйте, это обычная функция. и там уже сможете использовать

    Рейтинг: 0
  7. Большое спасибо автору!

    Рейтинг: 0
  8. Спасибо! В старых проектах была похожая функция, но найти так и не смог. А Google первым результатом привёл на эту статью.

    +1 в карму автору!

    Рейтинг: 0
  9. Давным давно искал решение проблемы окончаний и тут она решается!

    Рейтинг: 0
  10. В одну строку на javascript. Для PHP смысл тот же

    function plural (num, word) {
    return (num % 10 == 1 && num % 100 != 11) ? word[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 14)) ? word[1] : word[2];
    }

    Рейтинг: 0
  11. Тоже писал такую функцию, только для вывода использовал sprintf( $str, $num ). Это позволяет использовать конструкции вида: «получен 1 комментарий», «получено 2 комментария», … — передавая в функцию строки: «получено %d комментария»…

    Рейтинг: 0

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

Политика конфиденциальности

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

Принять