Генерация формы множественного числа

253
02 апреля 2017, 05:27

Здравствуй, дали задачу по PHP

Напишите массив с числами от 1 до 30 [1, 2, 3 ....] и функцию, которая делает следующее проходит по массиву и каждому числу дописывает фразу "новых комментариев" и эти слова склоняются в соответствии с их числом и делает в итоге массив 1 новый комментарий 2 новых комментария и тд и вывести на экран в html в элементе

Прошу помочь с примерами решения, в PHP я новичок, теорию изучил не плохо но сижу несколько дней и не дошло пока что использовать в этом примере.

Answer 1

Есть статья относительно множественных чисел. Там собраны алгоримы определения множественного числа для многих стран. Алгоритмы представлены в виде формул. Не нужно изобретать велосипед. Мы же используем формулы в математике.

В данном случае мы берем русский язык: nplurals=3 То есть для русского языка три множественные формы:
1) Когда элемент один. Например: 1 новый комментарий
2) Когда элементов больше двух, но меньше пяти. Например: 3 комментария, 4 комментария
3) Когда элементов больше или равно пяти. Например: 5 новых комментариев, 6 новых комменариев

Теперь перейдем к реализации. Условия привел в более читаемый вид:

$numbers = ['1', '2', '3', '4', '5'];
function plural($number)
{
    if ($number % 10 == 1 && $number % 100 != 11) {
        return $number . ' новый комментарий';
    } else {
        if ($number % 10 >= 2 && $number % 10 <= 4 && ($number % 100 < 10 || $number % 100 >= 20)) {
            return ($number . ' новых комментария');
        } else {
            return ($number . ' новых комментариев');
        }
    }
}
foreach ($numbers as $number) {
    echo plural($number);
    echo '<br>';
}
Answer 2

На мой взгляд самое элегантное решение функции plural такое:

function plural($number, $array){
   $keys = [2, 0, 1, 1, 1, 2];
   return $array[$number % 100 > 4 && $number % 100 < 20 ? 2 : $keys[min($number % 10, 5)]];
}

Как это работает:

Есть массив со склонениями

$array[' новый комментарий', ' новых комментария', ' новых комментариев']

Cоставляем массив ключей $keys = [2, 0, 1, 1, 1, 2];

  • $keys[0] = 2;$array[2] = 'новых комментариев' → 0, 20, 30, 10020... 'новых комментариев'

  • $keys[1] = 0;$array[0] = 'новый комментарий' → 1, 21, 31... 'новый комментарий'

  • $keys[2] = $keys[3] = $keys[4] = 1;$array[1] = 'новых комментария' → 2, 3, 4, 31, 32, 33, 34 ... 'новых комментария'

  • $keys[5] = 2; → после 5-х всегда 'новых комментариев' → 5 'новых комментариев', 1006 'новых комментариев'

Поэтому $array[$keys[min($number%10, 5)]];

На этом бы можно было закончить, НО...есть 11, 12, 13 'новый комментарий' — это исключение. Запишем $number % 100 > 4 && $number % 100 < 20 ? 2

Итак, разобрались с выражением $number%100 > 4 && $number%100 < 20 ? 2: что если остаток отделения в пределах 4–20, то всегда - новых комментариев.

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

$arrays = [1,2,3,4,5,6,7,8,9,10];
foreach($arrays as $key=>$val) {
   $arrays[$key] .= plural($val, array(' новый комментарий', ' новых комментария', ' новых комментариев'));
}
var_dump($arrays);

Обновлено

Почему такой порядок ключей? $keys = [2, 0, 1, 1, 1, 2];

Есть массив ключей $keys = [2, 0, 1, 1, 1, 2]; и массив склонений $array[' новый комментарий', ' новых комментария', ' новых комментариев'].
Для простоты рассмотрим значения от 0- 10:

0 - $keys[0] = 2, а $array[2] = "..ев";
1 - $keys[1] = 0, а $array[0] = "..й";
2 - $keys[2] = 1, а $array[1] = "..я";
3 - $keys[3] = 1, а $array[1] = "..я";
4 - $keys[4] = 1, а $array[1] = "..я";

а всё что после пяти это будет "...ев";

5,6,7,8,9 - $keys[5] = 2 $array[2] "..ев"; По такому принципу можно склоняются все числа кроме 11,12,13,14

Answer 3
<?php
function fornum($count, $ie, $re, $rm){
    $div = ($count / 10) % 10;
    $mod = $count % 10;
    if ($div != 1) {
        if ($mod >= 2 && $mod <= 4) {
            $use = $re;
        } else if ($mod == 1) {
            $use = $ie;
        } else {
            $use = $rm;
        }
    } else {
        $use = $rm;
    }
    return $use;
}
for ($i = 0; $i < 102; $i++)
    echo $i.' '.fornum($i, 'новый', 'новых', 'новых').' '.fornum($i, 'комментарий', 'комментария', 'комментариев').'<br/>';

(Вытащил из своего старого кода. Как работает, уже не помню.)

READ ALSO
Объединиение или наследование C++

Объединиение или наследование C++

Всем привет, разрабатываю язык программирования на c++ (надо для учёбы), но в плюсах я пока новичок, и отсюда возникают различные вопросы из раздела...

312
Количество вхождений паттерна в строке C++

Количество вхождений паттерна в строке C++

Привет всем! Как посчитать количество вхождений паттерна regex в сроке? Язык С++

210
Не работает метод write.string(*str) в rapidjson, как решить?

Не работает метод write.string(*str) в rapidjson, как решить?

На вход в json передаю vector<string>vecs, но выдает ошибку(коммит в конце), помогите решить

269
Как прочитать большой файл в QByteArray

Как прочитать большой файл в QByteArray

Не читается большой файл в QByteArray (182111787 byte):

326