Как сделать склонение числительных на javascript.

Как сделать склонение числительных на javascript.

@volond

Без склонения числительных пользователь может увидеть «8 мортышка(ек)» или «4 трамваев» и т.д. Это не красиво и усложняет процесс восприятия интерфейса.

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

Как сделать склонение числительных на javascript

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

Ниже приведена функция, которая выполняет склонение числительных на javascript:


function declOfNum(number, words) {

    return words[(number % 100 > 4 && number % 100 < 20) ?

        2 : [2, 0, 1, 1, 1, 2][(number % 10 < 5) ?

            number % 10 : 5

        ]];

}


В эту функцию передается число (параметр number), и массив заголовков (параметр titles), среди которых будет выбрана правильная форма, подходящая к числу.

Первый элемент title — для единиц, второй — для пар, третия — для других чисел.

Например:

Нужно вывести фразу N арбузов, вызовем функцию:

title=declOfNum(N,['арбуз','арбуза','арбузов']);

В результате склонение числительных на javascript сработает, и мы получим (в зависимости от N):

1 арбуз
2 арбуза
12 арбузов

Всё просто, и удобно.

Еще одно применение пропишем правильно дату:

Но воспользуемся функцией каррирования

function curry(fn) {

    const arity = fn.length;


    return function $curry(...args) {

        if (args.length < arity) {

            return $curry.bind(null, ...args);

        }


        return fn.call(null, ...args);

    };

};

и перепишем функцию declOfNum

const curryDeclOfNum = curry((wordsMap, number, key) => {

    return wordsMap.get(key)[(number % 100 > 4 && number % 100 < 20) ?

        2 : [2, 0, 1, 1, 1, 2][(number % 10 < 5) ?

            number % 10 : 5

        ]];

})

теперь предыдущий пример выглядит так:

var wordsMap = new Map([

    [0, ['год', 'года', 'лет']],

    [1, ['день', 'дня', 'дней']],

    [2, ['час', 'часа', 'часов']],

    [3, ['минута', 'минуты', 'минут']],

    [4, ['секунда', 'секунды', 'секунд']]

])


var timeDeclOfNum = curryDeclOfNum(wordsMap)

var timeReducer = (t, n, i) => { return !n || [...t, `${n} ${timeDeclOfNum(n, i)}`] }

console.log([10, 45, 13, 1].reduce(timeReducer, []).join(' '))



или единицы измерения:

var wordsMapEd = new Map([

    ['шт.', ['штука', 'штуки', 'штук']],

    ['кг.', ['килограмм', 'килограмма', 'килограммов']],

])

var edDeclOfNum = curryDeclOfNum(wordsMapEd)

var edReducer = (t, word) => {

    var [n, key] = word.split(' ')

    return !n || [...t, `${n} ${edDeclOfNum(+n, key)}`]

}

console.log(['10 шт.', "45 кг.", "13 шт.", "1 кг."].reduce(edReducer, []).join(' '))




Report Page