вернуться к уроку

Разобрать выражение

Арифметическое выражение включает два числа и оператор между ними. Например:

  • 1 + 2
  • 1.2 * 3.4
  • -3 / -6
  • -2 - 2

Оператором может быть: "+", "-", "*" или "/".

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

Создайте функцию parse(expr), которая принимает выражение и возвращает массив из трёх элементов:

  1. Первое число.
  2. Оператор.
  3. Второе число.

Например:

let [a, op, b] = parse("1.2 * 3.4");

alert(a); // 1.2
alert(op); // *
alert(b); // 3.4

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

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

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

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

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

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

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

Для получения этих частей в виде отдельных элементов массива-результата давайте вставим скобки вокруг каждой из них, получится (-?\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) (.\d+) можно убрать из массива, добавив ?: в начало: (?:\.\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