zpět k lekci

Parsujte výraz

Aritmetický výraz se skládá ze 2 čísel a operátoru mezi nimi, například:

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

Operátor je jeden z následujících: "+", "-", "*" nebo "/".

Na začátku, na konci i mezi jednotlivými částmi mohou být dodatečné mezery.

Vytvořte funkci parsuj(výraz), která vezme výraz a vrátí pole 3 prvků:

  1. První číslo.
  2. Operátor.
  3. Druhé číslo.

Příklad:

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

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

Regulární výraz pro číslo je: -?\d+(\.\d+)?. Vytvořili jsme ho v předchozí úloze.

Operátor je [-+*/]. Pomlčka - je v hranatých závorkách uvedena jako první, protože uprostřed by znamenala rozsah znaků, ale my potřebujeme právě znak -.

Lomítko / by mělo být v JavaScriptovém RV /.../ předznamenáno únikovým znakem, uděláme to později.

Potřebujeme číslo, operátor a pak další číslo. A nepovinné mezery mezi nimi.

Celý regulární výraz: -?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?.

Má 3 části a mezi nimi je \s*:

  1. -?\d+(\.\d+)? – první číslo,
  2. [-+*/] – operátor,
  3. -?\d+(\.\d+)? – druhé číslo.

Aby z každé z těchto částí vznikl samostatný prvek v poli výsledků, uzavřeme je do závorek: (-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?).

V akci:

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

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

Výsledek obsahuje:

  • výsledek[0] == "1.2 + 12" (celá shoda)
  • výsledek[1] == "1.2" (první skupina (-?\d+(\.\d+)?) – první číslo včetně desetinné části)
  • výsledek[2] == ".2" (druhá skupina(\.\d+)? – první desetinná část)
  • výsledek[3] == "+" (třetí skupina ([-+*\/]) – operátor)
  • výsledek[4] == "12" (čtvrtá skupina (-?\d+(\.\d+)?) – druhé číslo)
  • výsledek[5] == undefined (pátá skupina (\.\d+)? – poslední desetinná část chybí, takže je undefined)

Chceme jen čísla a operátor, ne celou shodu nebo desetinné části, takže výsledek trochu „pročistíme“.

Celou shodu (první prvek pole) můžeme odstranit posunem pole výsledek.shift().

Skupiny obsahující desetinné části (skupiny 2 a 4) (.\d+) můžeme vyloučit přidáním ?: na začátek: (?:\.\d+)?.

Konečné řešení:

function parsuj(výraz) {
  let rv = /(-?\d+(?:\.\d+)?)\s*([-+*\/])\s*(-?\d+(?:\.\d+)?)/;

  let výsledek = výraz.match(rv);

  if (!výsledek) return [];
  výsledek.shift();

  return výsledek;
}

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

Alternativou k použití nezachytávacího ?: by bylo pojmenování skupin, například:

function parsuj(výraz) {
  let rv = /(?<a>-?\d+(?:\.\d+)?)\s*(?<operátor>[-+*\/])\s*(?<b>-?\d+(?:\.\d+)?)/;

  let výsledek = výraz.match(rv);

  return [výsledek.groups.a, výsledek.groups.operátor, výsledek.groups.b];
}

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