Qualcosa è andato storto e gli elfi hanno fatto un piccolo pasticcio. Alcuni dei regali sono finiti in mezzo alla neve e i cartellini con i nomi si sono rovinati. Per fortuna la maggior parte delle lettere dei nomi sono visibili. Babbo Natale è convinto si possa ricostruire il nome intero a partire dai frammenti.
Il problema: Matching Gift Names 🎁

Il problema di oggi, il numero 7 del Dev Advent Calendar 🎅 è molto veloce. Ma richiede di usare le regular expressions. Onestamente faccio ancora fatica a maneggiare questo aspetto di JavaScript: trovo difficoltà anche con un problema semplice come questo.
Comincio con la soluzione:
import { default as names } from "../data/names.js";
export const matchedNames = (smudgedName) => {
const nameWithRegex = smudgedName.replace(/#/gu, ".");
const regex = new RegExp(`^${nameWithRegex}$`, "gu");
return names.filter((name) => name.search(regex) > -1);
};
Allora, il primo passo, per me, è di provare varie combinazioni di regex e vedere qual è più adatta al problema. Per fare questo uso un sito molto ben fatto, regex101 e faccio un po’ di test manuali. Dopo aver individuato la regola (spero) giusta passo a creare la regular expression.
Ci sono due modi. Quello che finora ho usato più spesso è così:
const re = /hello/gu;
In genere è la soluzione migliore perché quella più efficiente. Prevede però di conoscere già in partenza l’espressione da usare. Non è questo il caso di oggi. Devo creare una regex diversa per ogni nome da controllare. Uso quindi:
const nameWithRegex = "hello";
const re = new RegExp(nameWithRegex, "gu");
Ovviamente questo codice funziona solamente se voglio cercare la parola hello
. Non è questo il mio scopo.
Per prima cosa prendo la parola rovinata e sostituisco il carattere #
con il carattere .
. Come mai? Perché il punto, nelle regex, indica un singolo carattere qualsiasi. In questo modo posso trasformare h#ello
nella stringa h.ello
da usare direttamente come regex nel passaggio successivo. Quindi, scritto in codice:
const nameWithRegex = smudgedName.replace(/#/gu, ".");
Il passaggio successivo richiede osservare com’è la lista dei nomi. Poiché si tratta di un array ogni nome è a se stante. Posso quindi dare per scontato che il confronto avvenga tra stringhe complete. Aggiungo quindi due comandi:
^
indica che il pattern da trovare è all’inizio della stringa$
indica che dopo l’ultimo carattere del pattern non c’è più nulla.
In questo modo mi assicuro che patt.
restituisca solamente patty
e patti
ma non patterson
.
const regex = new RegExp(`^${nameWithRegex}$`, "gu");
Dopo aver trovato la regex da usare non resta che usarla effettivamente. Il problema è che non posso cavarmela con RegExp.prototype.test(). Il problema è che test()
fa ricominciare la ricerca sempre dall’ultimi risultato trovato. Questo genera dei bug: credo che senza i test sul codice avrei avuto molte difficoltà a comprendere questo inghippo.
Di conseguenza ho deciso di usare String.prototype.search(): questo metodo fa partire la ricerca sempre dalla posizione 0
, ed è esattamente quello che serve a me.
return names.filter((name) => name.search(regex) > -1);
Bene, questo è tutto per oggi.
Chi invece è curioso di leggere le puntate precedenti di questa serie di articoli sul 🎅 Dev Advent Calendar, può seguire questi link: