How to avoid value repeats in this code?

Asked

Viewed 103 times

1

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óúàô'));

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

It works perfect, but I’m intrigued with repetitions and a 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 it this way, how could I get the value of the item in the object acc when the replace marry a sharp letter?

  • See this: https://answall.com/a/54426/132

  • I’m sure it’s duplicate, but I didn’t find any good question to put as duplicate.

  • rsrs.. try to find it. Isac’s answer is good.

  • I found some that were poorly formulated. But then I think it is not good to mark as duplicate.

4 answers

6


For the second case how each letter is inside a string can traverse the strings through Object.keys and see if it has the letter indexOf. If found 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óúàô'));

May place a return m; at the end of the font replacement function if you want to guard against the case of not having a letter in acc for which you are applying regex. In this case instead of catching undefined would get the same input letter.

  • +1 for the excellent answer.

  • I just think that the return m;it is not necessary... if you do a test with a string without accent it will return itself.

  • the first return already returns the received string as it is. replace is only optional if there is some match

  • @dvd Yes it is true but I was referring to the match of something that was forgotten (lapse of the same programmer), as for example not having the 'ú':'u' in acc and continue to replace with /[...ú]/.

4

Based in this other answer of mine 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.

4

You can do it this way 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óúàô'));

2

My answer is similar to @Isac’s, only changing the syntax instead of using for of, used for in. I’ll leave it 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"

Browser other questions tagged

You are not signed in. Login or sign up in order to post.