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

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

Арифметическое выражение состоит из двух чисел и операции между ними, например:

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

Список операций: "+", "-", "*" и "/".

Также могут присутствовать пробелы вокруг оператора и чисел.

Напишите функцию, которая будет получать выражение и возвращать массив из трёх аргументов:

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

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

Оператор – это [-+*/]. Заметим, что дефис - идёт в списке первым, так как на любой позиции, кроме первой и последней, он имеет специальный смысл внутри [...], и его понадобилось бы экранировать.

Кроме того, когда мы оформим это в JavaScript-синтаксис /.../ – понадобится заэкранировать слэш /.

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

Полное регулярное выражение будет таким: -?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?.

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

Посмотрим в действии:

var re = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/;

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

Итоговый массив будет включать в себя компоненты:

  • result[0] == "1.2 + 12" (вначале всегда полное совпадение)
  • result[1] == "1" (первая скобка)
  • result[2] == "2" (вторая скобка – дробная часть (\.\d+)?)
  • result[3] == "+" (…)
  • result[4] == "12" (…)
  • result[5] == undefined (последняя скобка, но у второго числа дробная часть отсутствует)

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

Уберём её из запоминания, добавив в начало скобки ?:, то есть: (?:\.\d+)?.

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

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

  var result = expr.match(re);

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

  return result;
}

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