How to avoid value repetitions in this code?

2

I made the function below that removes accents from a string using values from an object:

function remAcentos(p){

   var acc = {
      //    ↓         ↓         ↓         ↓         ↓
      'á': 'a', 'â': 'a', 'à': 'a', 'ã': 'a', 'â': 'a',
      //    ↓         ↓
      'é': 'e', 'ê': 'e',
      'í': 'i',
      //    ↓         ↓         ↓
      'ó': 'o', 'õ': 'o', 'ô': 'o',
      'ú': 'u'
   }

   return p.replace(/[áàãâéêíóõôú]/g, function(m){

       return acc[m];
      
   });

}

console.log(remAcentos('brásíliaóúàô'));

It has a replace with a regex that matches accented letters and replaces the value of the item in the object and returns the string without the accents.

It works perfect, but I'm intrigued by repetitions and a little bit with the aesthetics of the code (see the indicative arrows in the code) and I think this can be optimized without repetitions.

How could I avoid such repetitions? I thought of something like:

var acc = {
   'áâàãâ': 'a',
   'éê': 'e',
   'í': 'i',
   'óôõ': 'o',
   'ú': 'u'
}

But if I do this way, how could I get the value of the item in the acc object when the replace marries an accented letter?

    
asked by anonymous 18.03.2018 / 00:55

4 answers

5

For the second case as each letter is within a string you can scroll through strings through Object.keys and see if you have the indexOf . If find returns the associated value.

Example:

function remAcentos(p){

   var acc = {
       'áâàãâ': 'a',
       'éê': 'e',
       'í': 'i',
       'óôõ': 'o',
       'ú': 'u'
   }

   return p.replace(/[áàãâéêíóõôú]/g, function(m){
       for (let chave of Object.keys(acc)){
           if (chave.indexOf(m) !== -1){
               return acc[chave];
           }
       }     
   });

}

console.log(remAcentos('brásíliaóúàô'));

You can put a return m; at the end of the letter substitution function if you want to guard against the case of not having a letter in acc to which you are applying the regex. In that case instead of catching undefined would get the same input letter.

    
18.03.2018 / 01:14
4

Based on in my other answer here :

function eliminarAcento(palavra) {
  var latinoMaiusculo = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var latinoMinusculo = "abcdefghijklmnopqrstuvwxyz";
  var cirilicoMaiusculo = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ";
  var cirilicoMinusculo = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя";
  var gregoMaiusculo = "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ";
  var gregoMinusculo = "αβγδεζηθικλμνξοπρστυφχψω";

  function eliminarAcentoLetra(letra) {
    var acentos = [
      {de: "áåãàâä", para: "a"},
      {de: "ÁÅÃÀÂÄ", para: "A"},
      {de: "éêèë", para: "e"},
      {de: "ÉÊÈË", para: "E"},
      {de: "íîìï", para: "i"},
      {de: "ÍÎÌÏ", para: "I"},
      {de: "óõòôö", para: "o"},
      {de: "ÓÕÒÔÖ", para: "O"},
      {de: "úùûü", para: "u"},
      {de: "ÚÙÛÜ", para: "U"},
      {de: "ý", para: "y"},
      {de: "Ý", para: "Y"},
      {de: "ç", para: "c"},
      {de: "Ç", para: "C"},
      {de: "ñ", para: "n"},
      {de: "Ñ", para: "N"},
      {de: "ά", para: "α"},
      {de: "έ", para: "ε"},
      {de: "ή", para: "η"},
      {de: "ίϊ", para: "ι"},
      {de: "ό", para: "ο"},
      {de: "ύϋ", para: "υ"},
      {de: "ώ", para: "ω"},
      {de: "Ά", para: "Α"},
      {de: "Έ", para: "Ε"},
      {de: "Ή", para: "Η"},
      {de: "ΊΪ", para: "Ι"},
      {de: "Ό", para: "Ο"},
      {de: "ΎΫ", para: "Υ"},
      {de: "Ώ", para: "Ω"},
      {de: "ς", para: "σ"}
    ];
    for (var e in acentos) {
      for (var a = 0; a < acentos[e].de.length; a++) {
        if (letra === acentos[e].de[a]) return acentos[e].para;
      }
    }
    return letra;
  }

  var s = "";
  for (var i in palavra) {
    s += eliminarAcentoLetra(palavra[i]);
  }
  return s;
}

// teste
var x = "Conceição Хорошо Ελληνικό";
alert("'" + x + "' sem acentos é '" + eliminarAcento(x) + "'");

Works for Latin, Cyrillic and Greek alphabets.

    
18.03.2018 / 01:20
4

You can do this too:

function remAcentos(p){

  var acc = {
    'áâàãâ': 'a',
    'éê': 'e',
    'í': 'i',
    'óôõ': 'o',
    'ú': 'u'
  }

  return p.replace(/[áàãâéêíóõôú]/g, letra => {
  let re;
    Object.keys(acc).forEach(item => (item.indexOf(letra) !== -1) && (re = acc[item]));
    return re;
  });

}

console.log(remAcentos('brásíliaóúàô'));
    
18.03.2018 / 01:58
2

My response is similar to @Isac, just changing the syntax, instead of using for of , I used for in . I'll leave as a reference:

function remAcentos(p){

   var acc = {
      'áâàãâ': 'a',
      'éê': 'e',
      'í': 'i',
      'óôõ': 'o',
      'ú': 'u'
   }

   return p.replace(/[áàãâéêíóõôú]/g, function(m){

      for(var key in acc){
         if(~key.indexOf(m)) return acc[key];
      }
      
   });

}

console.log(remAcentos('brásíliaóúàô')); // retorna "brasiliaouao"
console.log(remAcentos('brasilia')); // retorna "brasilia"
    
18.03.2018 / 02:01