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 substr
vez de slice
.
Outras soluções que tentei envolver split
ou RegExp
tiveram um grande impacto no desempenho e foram cerca de 2 ordens de magnitude mais lentas. Usar join
os 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 split
cria) 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 RegExp
ou split
e 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.