Eu não usaria filter
desta forma. Isso porque cada chamada de filter
percorre o array e retorna outro. Mesmo que o filtro remova alguns elementos, ainda sim na prática vc está percorrendo várias vezes o array (no pior caso, todos os elementos), e retornando outros arrays intermediários no meio do processo.
Além disso, o nome não está bom. Eu entendi que se letter
for true
, vc não quer remover as letras, e sim mantê-las. Por isso o remove
no início dos nomes dos filtros não me parece uma boa.
Enfim, minha sugestão é percorrer os caracteres apenas uma vez, e para cada um, vc aplica todos os filtros:
function filterChars(text, options) {
var result = '';
for (const char of text) {
if ((options.letter && /[a-z]/i.test(char))
|| (options.number && /[0-9]/.test(char))
|| (options.special && /[!@#$%]/.test(char))) {
result += char;
}
}
return result;
}
const alphabet = 'abcde123456!@#$%';
console.log(filterChars(alphabet, { letter: true, number: true, special: false })); // abcde123456
console.log(filterChars(alphabet, { letter: true, number: false, special: true })); // abcde!@#$%
console.log(filterChars(alphabet, { letter: false, number: true, special: true })); // 123456!@#$%
Repare que fiz o texto ser um parâmetro da função (da forma que vc fez, ela sempre verifica o mesmo texto). Assim fica mais flexível, pois vc pode passar qualquer outra string para a função.
Mas tem um detalhe: repare que a função ficou responsável por definir o que é uma letra, número ou caractere especial.
Uma forma mais flexível seria a função receber uma lista de filtros a serem aplicados. Aí para cada elemento, vc verifica se ele satisfaz algum deles:
function filterChars(text, filters) {
var result = '';
for (const char of text) { // para cada caractere do texto
// verifica se ele satisfaz algum filtro
for (const filter of filters) {
if (filter(char)) {
result += char;
break; // se já satisfaz um dos filtros, não preciso verificar os outros
}
}
}
return result;
}
// cada filtro é uma função que recebe um caractere e verifica se ele satisfaz determinada condição
function isLetter(char) {
return /[a-z]/i.test(char);
}
function isNumber(char) {
return /[0-9]/.test(char);
}
function isSpecial(char) {
return /[!@#$%]/.test(char);
}
const alphabet = 'abcde123456!@#$%';
console.log(filterChars(alphabet, [ isLetter, isNumber ])); // abcde123456
console.log(filterChars(alphabet, [ isLetter, isSpecial ])); // abcde!@#$%
console.log(filterChars(alphabet, [ isNumber, isSpecial ])); // 123456!@#$%
Assim fica mais flexível, pois as definições dos filtros ficam fora da função, e ela funcionará para quaisquer critérios que vc passar. E as funções dos filtros podem ser tão complexas quanto vc precisar, além de não se limitar a apenas um número fixo de opções.
E apesar de ter um loop dentro de outro, ainda é melhor do que chamar filter
várias vezes. Isso porque só percorremos os caracteres apenas uma vez e não criamos os arrays intermediários. E para cada caractere, percorremos o array de filtros, mas assim que um é satisfeito, interrompemos o loop interno e ele não verifica os demais.