Analizzate un'espressione
Un’espressione aritmetica consiste in 2 numeri e un operatore tra di essi, ad esempio:
1 + 2
1.2 * 3.4
-3 / -6
-2 - 2
L’operatore è uno fra: "+"
, "-"
, "*"
o "/"
.
Potrebbero esserci ulteriori spazi all’inizio, alla fine o tra gli elementi.
Create una funzione parse(expr)
che riceva un’espressione e restituisca un array di 3 elementi:
- Il primo numero.
- L’operatore.
- Il secondo numero.
Ad esempio:
let [a, op, b] = parse("1.2 * 3.4");
alert(a); // 1.2
alert(op); // *
alert(b); // 3.4
L’espressione regolare per un numero è: -?\d+(\.\d+)?
. L’abbiamo creata nell’esercizione precedente.
Per trovare un operatore usiamo [-+*/]
. Il trattino -
va posto all’inizio nelle parentesi quadre, in mezzo significherebbe un intervallo di caratteri, mentre noi vogliamo soltanto il carattere -
.
Dovremmo fare l’escape dello slash /
dentro una regexp JavaScript /.../
, lo faremo dopo.
Abbiamo bisogno di un numero, un operatore, e quindi un altro numero. Tra di essi ci possono essere spazi opzionali.
Ecco l’intera espressione regolare: -?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?
.
Questa consta di 3 parti, intervallate da \s*
:
-?\d+(\.\d+)?
– il primo numero,[-+*/]
– l’operatore,-?\d+(\.\d+)?
– il secondo numero.
Per rendere ciascuna di queste parti un elemento separato dell’array di risultati le racchiudiamo tra parentesi: (-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?)
.
In azione:
let regexp = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/;
alert( "1.2 + 12".match(regexp) );
Il risultato include:
result[0] == "1.2 + 12"
(l’intera corrispondenza)result[1] == "1.2"
(il primo gruppo(-?\d+(\.\d+)?)
, il primo numero compresa la parte decimale)result[2] == ".2"
(il secondo gruppo(\.\d+)?
, la prima parte decimale)result[3] == "+"
(il terzo gruppo([-+*\/])
, l’operatore)result[4] == "12"
(il quarto gruppo(-?\d+(\.\d+)?)
, il secondo numero)result[5] == undefined
(il quinto gruppo(\.\d+)?
, l’ultima parte decimale è assente, quindi equivale ad undefined)
Il nostro scopo è ottenere i numeri e l’operatore, senza l’intera corrispondenza o le parti decimali, quindi “puliamo” un po’ il risultato.
L’intera corrispondenza (il primo elemento dell’array) possiamo rimuoverla con result.shift()
.
I gruppi che contengono le parti decimali (gli elementi 2 e 4) (.\d+)
li escludiamo aggiungendo ?:
all’inizio: (?:\.\d+)?
.
La soluzione finale:
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