Replace a string’s letters with their respective alphabet position

Asked

Viewed 1,011 times

1

I need to replace each letter of any string with its position in the alphabet. For example, the string "faebcd" must become "615234".

I’m stuck at the replace values part of the array novaFrase by the respective values in the array posiçãoLetra. Follows the code:


const frase = "Birulei Nau"  // Frase de exemplo

const alfabeto = [,"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]; 

const posiçãoLetra = []; // Variável com a posição das letras do alfabeto

// A função abaixo encontra e preenche o array posiçãoLetra com as 
// respectivas posições das letras do alfabeto.

function encontraPosição (alfabeto) {    
    for (let i = 1; i < alfabeto.length; i++) {
        posiçãoLetra.push(alfabeto.indexOf(alfabeto[i],[0]));
    }
}

encontraPosição(alfabeto);


function substituiLetra (frase) {   

    const letrasFrase = frase.split('');
    const novaFrase = letrasFrase.forEach(function (letra){

        // Aqui que eu não to conseguindo destravar. 
        // Não sei se devo usar forEach, filter, map, etc...
        letra.splice(0, posiçãoLetra[0]) 

        console.log(novaFrase);

    });    
}

substituiLetra(frase);

4 answers

6

You said the string "faebcd" must become "615234". But what if the string is "klm", then she becomes "111213" (After all, "k", "l" and "m" are respectively the 11th, 12th and 13th letters of the alphabet)? To keep things simple, let’s assume that’s it. I’m also assuming other premises:

  • let’s consider only letters from A to Z (i.e., spaces, punctuation, digits, etc., all these will be ignored). I’ll also disregard accented letters.
    • it is not clear what you do with characters other than letters. In the code below, I will assume that the corresponding code is zero.
  • I’ll do the algorithm case insensitive: considers that both "A" and "a" will have the value 1, "B" and "b" will have the value 2, etc (one of the answers does not take this into account, so the letter "B" ends up having the value zero - I don’t know if that’s what you wanted, but anyway)

The other answers use a loop by the characters of the string, and within this loop use indexOf or map to check the position of the letter in the alphabet. So far so good, it works, but what you don’t realize is that these codes are creating a variation of the so-called Shlemiel the Painter’s Algorithm.

Basically, for each letter of the string, indexOf and map traverse the string (or array) alfabeto to check the position of the letter in it. That is, if the phrase is "Birulei Nau", for the letter "B", the alphabet is checked from the letter "a" (and if we do not consider the algorithm case insensitive, it will go through the whole alphabet, because it will not find the "B"). Then for the letter "i", check the alphabet again, starting from "a", then to the letter "r" same thing, and so on. At the end, the alfabeto is traversed several times (of course most of the time it will not be fully traversed, but even so are too many iterations for nothing, especially if the string has several characters that are not letters).

Anyway, another way of doing it would be:

let frase = "Birulei Nau";
let posicoes = [];
for (let i = 0; i < frase.length; i++) {
    let c = frase.codePointAt(i);
    // se for letra maiúscula, converte para minúscula
    if (65 <= c && c <= 90) c+= 32;
    if (97 <= c && c <= 122) {
        posicoes.push(c - 96);
    } else {
        posicoes.push(0); // não é letra de A a Z, usar zero
    }
}
console.log(posicoes.join(''));

I use codePointAt to obtain the value of code point of each character (to understand what this is, read here). To simplify, the letters from A to Z have code points with the same values as the ascii table, then we can take these values and manipulate them in a "smart" way to do what we need.

The capital letters are in the range between 65 and 90, and in this case just add 32 to get the respective lowercase letter (which in turn are in the range between 97 and 122, and so just subtract 96 to get the respective position of this in the alphabet). If you want the algorithm not to be case insensitive, just remove the first if.

Remember that I am considering that when the character is not a letter, I put the value zero. But if you want to ignore these characters, just remove the block else.

In the above case I used an array to store the positions and then joined everything with join. But you could also create a string directly and concatenate everything directly into it:

let frase = "Birulei Nau";
let posicoes = '';
for (let i = 0; i < frase.length; i++) {
    let c = frase.codePointAt(i);
    // se for letra maiúscula, converte para minúscula
    if (65 <= c && c <= 90) c+= 32;
    if (97 <= c && c <= 122) {
        posicoes += (c - 96);
    } else {
        posicoes += 0; // não é letra de A a Z, usar zero
    }
}
console.log(posicoes);

I did some tests and the above solutions proved faster than using indexOf. Of course, for a few small strings the difference will be insignificant, and maybe all this is just micro-optimization, but the alternative is there anyway.

3

To replace the letter with the position of the alphabet, just get the position of the letter in the Array with the method indexOf and add +1 since the elements in an Array start at zero position.

To also be more organized your code, you can transform your Array of letters into a single string, as strings are also sequences just like Arrays. See the example below:

const alfabeto = "abcdefghijklmnopqrstuvwxyz"; 

function obterPosicao(letra){
    return alfabeto.indexOf(letra) + 1;
}

To replace the letters of a sentence with positions, just transform the string into an Array, turn each letter into positions using the function obterPosicao with the method map and then put everything together in a string again with the join. See how it would look:

function substituiLetras(frase){
    frase = frase.split("");
    frase = frase.map(obterPosicao);
    frase = frase.join("");
    return frase;
}

What the method map returns a new Array with the values returned from a function callback (in this case the function is obterPosicao) passing the current array elements as parameter.

Already the method join serves to return a string with all elements of the Array separated by one separator (in case the separator is an empty string).

  • Okay, I think I get it. I’m going to test these codes. Thank you Jeanextreme002!

2


Can use .map(), but it takes some adjustments, as in case there are spaces in the sentence, eliminate them with replace:

frase.replace(/\s/g, '');

The expression /\s/g search all spaces.

Another thing is to convert the sentence to lower case, because in the case of a capital letter, as in your example "Birulei Nau", would not find the letters "B" and "N", since Javascript is case sentive (Differentiates uppercase and lowercase).

As in the Jeanextreme002 answer, you don’t need to create an array alfabeto, just a string with all letters, because each position of the characters has an index, similar to an array, starting from scratch (so it is necessary to add +1).

The code would look like this:

const frase = "Birulei Nau"  // frase de teste
const alfabeto = "abcdefghijklmnopqrstuvwxyz"; 

function substituiLetra (frase) {   
   frase = frase.replace(/\s/g, ''); // elimina os espaços
   const novaFrase = frase.split('').map(function (letra){
    
    // este trecho é apenas para mostrar os valores
    console.log(letra +" = "+ Number(alfabeto.indexOf(letra.toLowerCase())+1));
    // remova do código
   
   
      return alfabeto.indexOf(letra.toLowerCase())+1;
   }).join("");  

   return novaFrase; // retorna a string com as posições das letras
}

console.log("Posições: "+ substituiLetra(frase));

1

By the way your code is, it can be optimized by questions such as map usage, but the main one, never use special characters, especially in variable names, constants and/or functions. Follow an example by following your original code:

const frase = "Birulei Nau" // frase de teste

const alfabeto = [, "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];

const posiçãoLetra = []; // variável com a posição das letras do alfabeto

function encontraPosicao(letra) { // essa função encontra e preenche o array posiçãoLetra com as respectivas posições das letras do alfabeto.
  alfabeto.map((i, j) => {
    if (i === letra.toString().toLocaleLowerCase()) {
      return j;
    }
  })
}

encontraPosicao(alfabeto);


function substituiLetra(frase) {

  frase.split('').map((i, j) => {
    console.log(encontraPosicao(i));
  })

}

substituiLetra(frase);

Where, in each case of the repetition loop, it checks whether the array position refers to a letter identical to the letter it is in as parameter in the function call, thus returning the number of repetitions (letter number).

Browser other questions tagged

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