Solução mais rápida?
Fiz alguns benchmarks e esta solução ganhou imensamente: 1
str.slice(str.indexOf(delim) + delim.length)
// as function
function gobbleStart(str, delim) {
return str.slice(str.indexOf(delim) + delim.length);
}
// as polyfill
String.prototype.gobbleStart = function(delim) {
return this.slice(this.indexOf(delim) + delim.length);
};
Comparação de desempenho com outras soluções
O único candidato próximo era a mesma linha de código, exceto usando em substrvez de slice.
Outras soluções que tentei envolver splitou RegExptiveram um grande impacto no desempenho e foram cerca de 2 ordens de magnitude mais lentas. Usar joinos resultados de split, obviamente, adiciona uma penalidade de desempenho adicional.
Por que eles são mais lentos? Sempre que um novo objeto ou matriz tiver que ser criado, o JS precisará solicitar um pedaço de memória do sistema operacional. Este processo é muito lento.
Aqui estão algumas diretrizes gerais, caso você esteja buscando benchmarks:
- Novas alocações de memória dinâmica para objetos
{}ou matrizes [](como a que splitcria) custarão muito em desempenho.
RegExp as pesquisas são mais complicadas e, portanto, mais lentas que as pesquisas de string.
- Se você já possui uma matriz, a destruição de matrizes é tão rápida quanto explicitamente indexá-las e parece incrível.
Removendo além da primeira instância
Aqui está uma solução que dividirá até a nésima instância. Não é tão rápido, mas, na questão do OP, gobble(element, '_', 1)ainda é> duas vezes mais rápido que uma solução RegExpou splite pode fazer mais:
/*
`gobble`, given a positive, non-zero `limit`, deletes
characters from the beginning of `haystack` until `needle` has
been encountered and deleted `limit` times or no more instances
of `needle` exist; then it returns what remains. If `limit` is
zero or negative, delete from the beginning only until `-(limit)`
occurrences or less of `needle` remain.
*/
function gobble(haystack, needle, limit = 0) {
let remain = limit;
if (limit <= 0) { // set remain to count of delim - num to leave
let i = 0;
while (i < haystack.length) {
const found = haystack.indexOf(needle, i);
if (found === -1) {
break;
}
remain++;
i = found + needle.length;
}
}
let i = 0;
while (remain > 0) {
const found = haystack.indexOf(needle, i);
if (found === -1) {
break;
}
remain--;
i = found + needle.length;
}
return haystack.slice(i);
}
Com a definição acima, gobble('path/to/file.txt', '/')daria o nome do arquivo e gobble('prefix_category_item', '_', 1)removeria o prefixo como a primeira solução nesta resposta.
- Os testes foram executados no Chrome 70.0.3538.110 no macOSX 10.14.