Доброго времени суток, уважаемые.
Если Вы программируете уже долгое время, наверняка встречались с задачей вывода правильного окончания слова с предшествующим ему числом. примером может служить хотя бы блог, точнее, показ количества комментариев. в простейшем случае это может выглядеть так: Комментариев — 1. а порой хочется так: 1 комментарий и так: 5 комментариев.
К сути: решение не для жжёных опытных перцев, а для тех, кто столкнулся с задачей впервые. привожу код для 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) | |
текст для варианта «много» | |
днём интернета
шоколадкой для работы мозга
коробочкой ароматного чая для бодрости
продлением хостинга на +1 месяц
Спасибо что помогли
Юзай это. Проще меньше быстрее
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)]];
}
VICTOR_81, спасибо, вариант хороший, оценил; изящно.
но по тестам он быстрее не получился (php 5.2.13, разница составляет ~1.6 раза). да и проще его вряд ли можно назвать: множественные условия в одной строке заставляют немного подумать, прежде чем станет понятно, чего же, собственно, данный код делает.
Спасибо, лучшее что нашёл в поисковиках!
Только не кидайтесь камнями и не кройте (понятно чем)Вы тоже были маленькими. Блог на WordPress. Куда вставлять код?
2Foxbat
да хоть в код тем добавляйте, это обычная функция. и там уже сможете использовать
Большое спасибо автору!
да не за что, собственно
Спасибо! В старых проектах была похожая функция, но найти так и не смог. А Google первым результатом привёл на эту статью.
+1 в карму автору!
Давным давно искал решение проблемы окончаний и тут она решается!
В одну строку на 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];
}
Тоже писал такую функцию, только для вывода использовал
sprintf( $str, $num )
. Это позволяет использовать конструкции вида: «получен 1 комментарий», «получено 2 комментария», … — передавая в функцию строки: «получено %d комментария»…Согласен, sprintf() даже удобнее.