Estoy escribiendo una función Javascript para convertir una oración de primera persona a segunda persona. Mi función de prueba actual es la siguiente:
function statementCreator() { var sentence = "I went to the movies with my friend, Sally. Sally says that I'm her best friend."; var transforms = { "I" : "YOU", "ME" : "YOU", "MY" : "YOUR", "AM" : "ARE", "MINE" : "YOURS", "I'M" : "YOU'RE" }; var pattern = `\\b(?:${Object.keys(transforms).join('|')})\\b`; var re = new RegExp(pattern, "g"); str = sentence.toUpperCase().replace(re, matched => transforms[matched]); console.log(str); }Esto crea el siguiente patrón de expresiones regulares:
/\b(?:I|ME|MY|AM|MINE|I'M)\b/gLo que produce la siguiente salida:
YOU WENT TO THE MOVIES WITH YOUR FRIEND, SALLY. SALLY SAYS THAT YOU'M HER BEST FRIEND. Soy muy nuevo en Javascript y, por lo tanto, esta es probablemente una manera terrible de hacer esto y, por supuesto, esto también me deja con la palabra YOU'M como parte de mi salida.
Pero, idealmente, me gustaría una solución que pudiera:
${Object.keys(transforms).join('|')} )I'M .¿Cuál sería una buena manera de hacer esto y, en caso de que alguien conozca una forma completamente diferente en la que podría cambiar fácilmente de la primera a la segunda persona más fácilmente / correctamente, ME ENCANTARÁ esa respuesta también?
¡Gracias!
Los límites de palabras no darán el resultado correcto porque tiene caracteres que no son palabras como ' en I'M y dado I se coloca antes de I'M en alternancia \bI\b satisface la coincidencia en I'm y lo convierte en YOU'm .
Para abordar esto, puede usar esta solución con un enfoque ligeramente diferente en expresiones regulares, es decir
(?<!\w)(?:I|ME|MY|AM|MINE|I'M)(?![\w'])(?<!\w) : Lookbehind negativo para asegurarnos de que no tenemos un carácter de palabra antes de la coincidencia(?![\w']) : Negative Lookahead para asegurarnos de que no tenemos un carácter de palabra o ' después de la coincidenciaCódigo:
function statementCreator() { var sentence = "I went to the movies with my friend, Sally. Sally says that I'm her best friend. I, the current narrator, went to the movies."; var transforms = { "I" : "YOU", "ME" : "YOU", "MY" : "YOUR", "AM" : "ARE", "MINE" : "YOURS", "I'M" : "YOU'RE" }; var pattern = `(?<!\\w)(?:${Object.keys(transforms).join('|')})(?![\\w'])`; var re = new RegExp(pattern, "ig"); str = sentence.toUpperCase().replace(re, matched => transforms[matched]); console.log(str); } statementCreator();Si bien los límites de espacio en blanco funcionarán cuando esté seguro de que sus palabras siempre están entre caracteres de espacio en blanco o el inicio/final de la cadena, una solución más universal en este caso es simplemente ordenar las claves por longitud en orden descendente antes de crear el patrón de alternancia :
Object.keys(transforms).sort((a, b) => b.length - a.length)Esto soluciona el problema porque la primera alternativa encontrada impide que el motor de expresiones regulares pruebe el resto de las alternativas, consulte "Recuerde que el motor de expresiones regulares está ansioso" .
Vea la demostración de JavaScript:
function statementCreator() { var sentence = "I went to the movies with my friend, Sally. Sally says that I'm her best friend."; var transforms = { "I" : "YOU", "ME" : "YOU", "MY" : "YOUR", "AM" : "ARE", "MINE" : "YOURS", "I'M" : "YOU'RE" }; var keys = Object.keys(transforms).sort((a, b) => b.length - a.length); var pattern = `\\b(?:${keys.join('|')})\\b`; var re = new RegExp(pattern, "g"); str = sentence.toUpperCase().replace(re, matched => transforms[matched]); console.log(str); } statementCreator();Producción:
YOU WENT TO THE MOVIES WITH YOUR FRIEND, SALLY. SALLY SAYS THAT YOU'RE HER BEST FRIEND.