JavaScript | Как найти чётное число в строке?

JavaScript | Как найти чётное число в строке?

Есть строка:

let stroka = '23 cтроителя из бригады 15.0 залили 604,8 м бетона из необходимых 1042 м. Это -36 м от нормы.'

В этой строке есть 4 числа:

23
15.0
604,8
1042
-36

Нам нужно определить какое из них чётное.

 

Логика решения задачи

На самом первом этапе нужно определиться, какую часть символов из строки мы будем считать числом. Предлагаю учитывать любую последовательность из символов — «0123456789,.-«.

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

 

Поиск чисел-строк через регулярное выражение

Шаг № 1 — Вытаскиваем любые последовательности символов, похожие на числа

Мы создадим регулярное выражение. Оно будет сопоставляться глобально по всей строке при помощи метода [Symbol.match]. Внутри шаблона регулярного выражения будет жить Класс Символа с Квантификатором.

/([0123456789,.-])+/g[Symbol.match](stroka)

Такое сопоставление вернёт нам все возможные числа в виде массива, подходящие под условие отбора.

['23', '15.0', '604,8', '1042', '.', '-36', '.']

Скриншот из браузера:

Отобрали последовательности в строке, похожие на числа - JavaScript
Отобрали последовательности в строке, похожие на числа — JavaScript

 

Шаг № 2 — Фильтрация от нечётных и дробных

Теперь полученные результаты нам нужно отфильтровать. Нам не нужны числа, которые оканчиваются на нечётные цифры, а также нам не нужны числа, которые имеют точку или запятую.

 

Примечание!

Сейчас мы делаем так, потому что не ожидаем увидеть числа 14.00 или 14,00.

 

Внутри фильтра будет работать функция с таким условием:

!i.includes(/[.,]|[^02468]$/g.exec(i))

Мы пробрасываем в неё элемент массива i, у которого проверяется вхождение на:

  • символы точки и запятой — [.,]
  • отсутствие вхождения цифр 0, 2, 4, 6, 8 — [^02468]. Знак крышечки «^» обозначает отрицание в Классе Символа.

 

Почему отрицание на возврате includes()? Всё дело в работе метода exec()

/[.,]|[^02468]$/g.exec('23')
['3', index: 1, input: '23', groups: undefined]
/[.,]|[^02468]$/g.exec('15.0')
['.', index: 2, input: '15.0', groups: undefined]
/[.,]|[^02468]$/g.exec('604,8')
[',', index: 3, input: '604,8', groups: undefined]
/[.,]|[^02468]$/g.exec('1042')
null

По таким условиям, подходящие нам числа (которые строки) будут возвращать null после вызова exec(). На одном из этапов работы метода filter() срабатывает приведение к логическому типу Boolean().

Boolean(null)
false

Boolean(',')
true

Приведение null к логическому типу даёт false, но во всех найденных сопоставлениях будет true. Это значит, что для возврата нужного нам значения нужно поменять истину на ложь и ложь на истину, чтобы фильтр корректно отработал.

На выходе мы имеем:

/([0123456789,.-])+/g[Symbol.match](stroka).filter(i=>!i.includes(/[.,]|[^02468]$/g.exec(i)))
['1042', '-36']

 

Скриншот из браузера:

Получили чётные числа из строки - JavaScript
Получили чётные числа из строки — JavaScript

 

Учёт нулей после запятой или точки

Чётные числа могут быть записаны в формате дробной части, где после запятой или точки просто проставляются нули. Их количество может быть разной длины. Эта задача немного сложнее:

let str2 = 'Молоко3.0литра Творог2,00кг Сметана1.00литра Кефир0,0литра Простокваша,0000 Сыр.000 Орехи,0134 Картошка.735 Хлеб,521 Рис.04'

Ещё могут встретиться числа где опускается целая часть. Её бы тоже неплохо учитывать.

Как учитывать подобные числа?

 

Заменяем случаи на НОЛЬ:

  • ,0000
  • .000
  • 0,0

replace(/^(0+)*?[.,]0+$/, ‘0’)

 

Фильтруем результаты:

/([0123456789,.-])+/g[Symbol.match](stroka).map(i=>i.replace(/^(0+)*?[.,]0+$/, ‘0’)).filter(i=>!i.includes(/[^02468]([.,])?/g.exec(i)))

 

Информационные ссылки

Стандарт ECMAScripthttps://tc39.es/ecma262/multipage/

Стандарт ECMAScript — Раздел «22.2 RegExp (Regular Expression) Objects» — https://tc39.es/ecma262/multipage/text-processing.html#sec-regexp-regular-expression-objects