El Blog de Webcu

Aprendiendo de mis mentores

October 15, 2019

A lo largo de mi carrera he tenido buenas y malas experiencias que me han enseñado mucho. Algo que es un poco difícil es tener un mentor y uno bueno aun más. He tenido la suerte de tener varios. Recuerdo especialmente a la tutora de mis tesis de Pregrado y Maestría, la Doctora María Elena Martínez y al equipo de mi primera experiencia de trabajo en Canadá: SourceKnowledge, gracias a ellos la etapa de integración resultó mucho más llevadera. Fuera del ámbito profesional también he tenido la suerte de contar con amigos que han sido excelentes mentores.

Durante el desafio: Diseña tu entorno para lograr tus objetivos, que hice durante un mes, con Benjamin Hardy y Jonathan Levi, quedó aun más claro para mi la importancia de los mentores. Un mentor nos ayuda a descubrir nuestros puntos débiles y a mejorar nuestras habilidades. Es una relación que es realmente ganar-ganar para todos. El aprendiz se expone a nuevas ideas, pero al mismo tiempo puede aportar ideas interesantes a su mentor. Desde el punto de vista del mentor, él debe dominar correctamente el tema de estudio para poder explicar de una manera sencilla y eficaz a su aprendiz. Es por eso que debemos buscar proactivamente nuestros mentores y no dejar todo a la suerte. Después de cierto tiempo de búsqueda finalmente encontré un lugar que funciona muy bien de acuerdo a mis condiciones actuales. Gracias a Exercism he logrado encontrar un mentor que me ayude a mejorar mis habilidades en JavaScript.

Durante la última semana he aprendido mucho gracias a mi mentor ghjk. El intercambio que sucedió mientras hacía el ejercicio de Pangrama resultó verdaderamente interesante y productivo. Un pangrama es un texto que utiliza todas las letras posibles del alfabeto de un idioma.

Solución original:

export const isPangram = sentence => {
  const alphabet = new Set('abcdefghijklmnopqrstuvwxyz');

  [...sentence.toLowerCase()].forEach(function (letter) {
    if (alphabet.has(letter)) {
      alphabet.delete(letter);
    }
  });

  return alphabet.size === 0;
};

La idea es que creo un Set con todas las letras del alfabeto, entonces comienzo a recorrer el texto de entrada de la función y si la letra está en el alfabeto, entonces la elimino del alfabeto. Al finalizar el ciclo, el texto es un pangrama si el alfabeto está vacío. Estaba contento con mi solución.

Mejoras propuestas por el mentor

Esta solución, funciona correctamente pero se puede mejorar. Mi mentor señaló que utilizo una constante para declarar el alfabeto y después lo modifico. El me recomendó dos opciones para resolver el ejercicio sin modificar el alfabeto. Una usando el método every y otra utilizando un Set como en mi solución pero en vez de construirlo a partir del alfabeto y eliminar las letras que aparecian en el texto de entrada, construir uno con el texto de entrada y filtrarlo con las letras del alfabeto, de esa manera si al final el Set contiene 26 elementos es porque es un pangrama.

Constantes en JS

Para mi no era muy claro cómo funcionaban las constantes en JS, para ser sincero no había leído la sección del manual de JS acerca de las constantes, solo había visto algunos ejemplos, e infería que eran muy similar a las constantes en PHP. Yo pensaba que significaba que no podían cambiar el tipo, pero si su valor. Le pregunté a mi mentor si me podía explicar la diferencia entre usar let y const, porque al final ambas me permiten modificar un objeto. Mi mentor me explicó que para los tipos de datos primitivos como number/ boolean / string no podemos cambiar el valor de una constante, por ejemplo:

const someString = 'Hello, world!';
someString = 'Another string';  // TypeError: invalid assignment to const 'someString'

Pero para los objetos es diferente porque el valor son punteros a su contenido. Entonces no podemos asignar al puntero un nuevo valor, pero es totalmente valido cambiar un elemento del objeto.

const someArray = [1, 2, 3];
someArray = [ 4, 5, 6 ]; // TypeError: invalid assignment to const 'someArray'
someArray[0] = 0;        // OK -> Array(3) [ 0, 2, 3 ]

La regla que él utiliza es: emplear let si sabe que va a modificar el objeto después y si no lo va a modificar entonces utilizar const. El tema de las constantes en JS es interesante y tiene muchos detalles. Es una buena idea leer la documentación acerca de ellas: Constantes.

Primera Iteración

Basado en sus recomendaciones, cambie const por let e implementé dos nuevas soluciones:

Solución 1:

export const isPangramV2 = sentence => {
  const lowerCaseSentence = sentence.toLowerCase();

  return alphabetArray.every(function (letter) {
    return lowerCaseSentence.indexOf(letter) !== -1;
  })
};

const alphabetArray = [...'zqjxkvbywgpfmucdlhrsnioate'];

Esta función chequea que todas las letras del alfabeto están presentes en el texto. Aquí se me ocurrió la idea de organizar las letras del alfabeto en order creciente de la frecuencia de aparición de letras, porque de esa manera sería mucho más rapido encontrar los textos que no contenían una de las letras del alfabeto.

Solución 2:

export const isPangram = sentence => 26 === (new Set([...sentence.toLowerCase()].filter(character => alphabet.indexOf(character) !== -1)).size);

const alphabet = 'abcdefghijklmnopqrstuvwxyz';

Esta solución es mucho más concisa y creo que más eficiente para encontrar los textos que son Pangrama. Filtramos los caracteres del texto para solo dejar los que pertenecen al alfabeto y después creamos un set con ellos. Si el tamaño del Set es 26, significa que el texto contiene todas las letras del alfabeto. Una vez más estaba muy contento con mi solución y una vez más aprendí que aun se podia mejorar un poco.

Mejoras propuestas por el mentor

Acerca de la Solución 1 mi mentor me recomendó crear directamente un arreglo a partir del texto de entrada y filtrarlo con las letras del alfabeto solamente. De esa manera no necesito convertir el texto de entrada en un arreglo y el código es más conciso aún.

Acerca de la Solución 2 solo mencionó que desde el punto de vista de significado del código, era más explícito utilizar la función includes, pero que indexOf era más rápida.

Iteración Final:

Solución 1

export const isPangram = sentence => 26 === (new Set(sentence.toLowerCase().match(/[a-z]/g)).size);

Solución 2

export const isPangramV2 = sentence => {
  const lowerCaseSentence = sentence.toLowerCase();

  return alphabet.every(function (letter) {
    return lowerCaseSentence.includes(letter);
  })
};

const alphabet = [...'zqjxkvbywgpfmucdlhrsnioate'];

Gracias a ghjk y a todos los mentores que me ayudan a mejorar cada día.

Referencias


Jorge Glez

Escrito por Jorge Glez. Un ser humano con defectos y virtudes que intenta ser mejor cada día. Twitter