Skip to content

Latest commit

 

History

History
70 lines (45 loc) · 3.73 KB

File metadata and controls

70 lines (45 loc) · 3.73 KB

Регулярное выражение для числа: pattern:-?\d+(\.\d+)?. Мы создали его в предыдущей задаче.

Регулярное выражение для оператора pattern:[-+*/]. Дефис pattern:- стоит в начале квадратных скобок, потому что в середине этот символ будет означать диапазон, а нам нужен просто символ -.

Отметим, что косая черта должна быть экранирована внутри регулярного выражения JavaScript pattern:/.../, мы сделаем это позже.

Нам необходимо число, оператор и затем другое число. Между ними могут быть необязательные пробелы.

Полное выражение: pattern:-?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?.

Оно состоит из трёх частей, между которыми стоит pattern:\s*:

  1. pattern:-?\d+(\.\d+)? - первое число,
  2. pattern:[-+*/] - оператор,
  3. pattern:-?\d+(\.\d+)? - второе число.

Для получения этих частей в виде отдельных элементов массива-результата давайте вставим скобки вокруг каждой из них, получится pattern:(-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?).

В действии:

let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/;

alert( "1.2 + 12".match(regexp) );

Результат result включает в себя:

  • result[0] == "1.2 + 12" (полное совпадение)
  • result[1] == "1.2" (первая группа (-?\d+(\.\d+)?) -- первое число, включая десятичную часть)
  • result[2] == ".2" (вторая группа (\.\d+)? -- первая десятичная часть)
  • result[3] == "+" (третья группа ([-+*\/]) -- оператор)
  • result[4] == "12" (четвёртая группа (-?\d+(\.\d+)?) -- второе число)
  • result[5] == undefined (пятая группа (\.\d+)? -- вторая десятичная часть отсутствует, поэтому значение undefined)

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

Первый элемент массива (полное совпадение) можно удалить при помощи сдвига массива result.shift().

Группы, которые содержат десятичную часть (номер 2 и 4) pattern:(.\d+) можно убрать из массива, добавив pattern:?: в начало: pattern:(?:\.\d+)?.

Итоговое решение:

function parse(expr) {
  let regexp = /(-?\d+(?:\.\d+)?)\s*([-+*\/])\s*(-?\d+(?:\.\d+)?)/;

  let result = expr.match(regexp);

  if (!result) return [];
  result.shift();

  return result;
}

alert( parse("-1.23 * 3.45") );  // -1.23, *, 3.45

В качестве альтернативы исключению из запоминания pattern:?: мы могли бы использовать именованные группы следующим образом:

function parse(expr) {
  let regexp = /(?<a>-?\d+(?:\.\d+)?)\s*(?<operator>[-+*\/])\s*(?<b>-?\d+(?:\.\d+)?)/;

  let result = expr.match(regexp);

  return [result.groups.a, result.groups.operator, result.groups.b];
}

alert( parse("-1.23 * 3.45") );  // -1.23, *, 3.45;