Quiero dividir una cadena con acento con una consulta sin acento.
Este es mi código por el momento:
const sanitizer = (text: string): string => { return text .normalize("NFD") .replace(/\p{Diacritic}/gu, "") .toLowerCase(); }; const splitter = (text: string, query: string): string[] => { const regexWithQuery = new RegExp(`(${query})|(${sanitizer(query)})`, "gi"); return text.split(regexWithQuery).filter((value) => value); };Y este es el archivo de prueba:
import { splitter } from "@/utils/arrayHelpers"; describe("arrayHelpers", () => { describe("splitter", () => { const cases = [ { text: "pepe dominguez", query: "pepe", expectedArray: ["pepe", " dominguez"], }, { text: "pépé dominguez", query: "pepe", expectedArray: ["pépé", " dominguez"], }, { text: "pepe dominguez", query: "pépé", expectedArray: ["pepe", " dominguez"], }, { text: "pepe dominguez", query: "pe", expectedArray: ["pe", " pe", " dominguez"], }, { text: "pepe DOMINGUEZ", query: "DOMINGUEZ", expectedArray: ["pepe ", "DOMINGUEZ"], }, ]; it.each(cases)( "should return an array of strings with 2 elements [pepe, dominguez]", ({ text, query, expectedArray }) => { // When I call the splitter function const textSplitted = splitter(text, query); // Then I must have an array of two elements expect(textSplitted).toStrictEqual(expectedArray); } ); }); });El problema es con el segundo caso:
{ text: "pépé dominguez", query: "pepe", expectedArray: ["pépé", " dominguez"], } porque la consulta higienizada pepe tambien es pepe , asi que no en pepe Pépé dominguez . No sé cómo lograr en este caso que la función splitter devuelva ['pépé', 'dominguez'] .
Estoy buscando un resultado con el texto original, no un texto desinfectado
La única opción que se me ocurre es mantener un mapa de posibles opciones para tus cartas y luego construir la consulta dinámicamente:
// Get query with each letter being one of its options const sanitizeQuery = (query) => { const sanitizerMap = { 'e': ['é'] } return query .split('') .map(l => sanitizerMap[l] !== undefined ? `(?:${l}|${sanitizerMap[l].join('|')})` : l ) .join(''); } // Split text by a sanitzed query const splitter = (text, query) => { const regexWithQuery = new RegExp(`(${sanitizeQuery(query)})`, "gi"); return text.split(regexWithQuery).filter((value) => value); }; // Test const query = 'pepe'; console.log('Query Regex:', sanitizeQuery(query)); console.log('Output:', splitter('pépé dominguez', query));Puede optimizar esto colocando las opciones para las letras en una cadena en lugar de una matriz.
Sugerencia: ?: en la expresión regular significa que el resultado no se capturará. Si no se usa, cada letra que coincida estará en la matriz de salida. Lea más sobre esto aquí: ¿Qué es un grupo que no captura en expresiones regulares?