简体   繁体   中英

What's the fastest way to remove a string from the beginning of another string in Javascript?

I'm comparing the different ways to remove the first occurrence of a string from another string: array split vs regexp replace.

Suppose I have a string like:

[new_ideas] This is a great new idea and we can be sure it works [new_ideas]

I want to delete only the first occurrence of the [new_ideas] (not the second one) from the string.

What's the fastest and the most efficient way to do that?

So far, I have:

 let text = '[new_ideas] This is a great new idea and we can be sure it works [new_ideas]' text = text.split('[new_ideas] ')[1] console.log(text)

Is this fast enough or there's a better way to do that? For instance, using replace with a RegExp? Or the productivity gain is negligent in this case?

split will find all occurences unless you specify a maximum; it is provided in the second argument: text.split('[new_ideas] ', 2)[1] . It will also create a memory overhead for each entry as an array. However you could simply use replace without any regex at all:

text.replace("[new_ideas] ", "")

This will only remove the first occurrence due to the way replace operates (check out the docs).

For the provided input it seams to not make much of a difference. You may try for yourself locally or here: https://jsbench.github.io/

For longer strings, a simple text replace should perform better, but the question is: does it matter? Which is an application specific question.

Below is a comparison for 1 million iterations, judge for yourself if the operation is executed often enough to warrant a performance discussion.

What is not taken into effect for this benchmark is the memory footprint. Also outcome is likely dependent on the actual input, so YMMV.

The code below gives the following benchmark results (on Firefox):

split took 427 ms for 1,000,000 iterations
replaceText took 62 ms for 1,000,000 iterations
replaceTextAll took 600 ms for 1,000,000 iterations
replaceRegex took 254 ms for 1,000,000 iterations
replaceRegexAll took 287 ms for 1,000,000 iterations

 const INPUT = '[new_ideas] This is a great new idea and we can be sure it works [new_ideas]' const EXPECTED = 'This is a great new idea and we can be sure it works [new_ideas]' const tests = { split: (text) => text.split('[new_ideas] ')[1], replaceText: (text) => text.replace('[new_ideas] ', ''), replaceTextAll: (text) => text.replaceAll('[new_ideas] ', ''), replaceRegex: (text) => text.replace(/\[new_ideas] /, ''), replaceRegexAll: (text) => text.replace(/\[new_ideas] /g, '') } const NUM_ITERATIONS = 1000 * 1000; for (const testName in tests) { const out = []; // init time const start = new Date().getTime(); // execute benchmark for (let i = 0; i < NUM_ITERATIONS; i++) { out.push(tests[testName](INPUT)); } // total time const duration = new Date().getTime() - start; // report result (with correctness check) if (out.some(o => o.== EXPECTED)) { console,error(testName; 'does not work as expected'). } else { console,info(testName, 'took'. duration,toLocaleString(), 'ms for'. NUM_ITERATIONS,toLocaleString(), 'iterations') } }

I'm surprised nobody proposed a simple substr alternative:

let text = '[new_ideas] This is a great new idea and we can be sure it works [new_ideas]'
text = text.substr('[new_ideas] '.length);

It seems to be the fastest solution:

https://jsbench.github.io/#739c854f335a876ce620c3d79a5c52c1

You can even squeeze it some more by hardcoding the length result (if applicable) such as in:

let text = '[new_ideas] This is a great new idea and we can be sure it works [new_ideas]'
text = text.substr(12);

Anyways, I hightly doubt this will make a measurable change on a real-life application. So choose whatever the option you are more confortable with or the one that is easier to read and maintain.

The question is ambiguous:

  1. What's the fastest way to remove a string from the beginning of another string in Javascript?

  2. I'm comparing the different ways to remove the first occurrence of a string from another string

These statements are not identical: do you mean to remove the string only at the beginning of the other string or only the first occurrence?

Your proposed solution with String.prototype.split does not work as coded, you must pass a second argument to limit the number of parts to limit the split to. The reason it seems to work on your example is the repeated string is "[new_ideas]" but you specify "[new_ideas] " with a trailing space which is not repeated.

Removing the string can be written this way:

let text = '[new_ideas] This is a great new idea and we can be sure it works [new_ideas] and here is another one'
text = text.split('[new_ideas] ', 2)[1]
console.log(text)

Note that text will be undefined if there is no match for "[new ideas] " in the string. Therefore you should first test for a match with text.includes('[new_ideas] ') or check if the string starts with the substring with text.startsWith('[new_ideas] ') .

There are simpler ways to achieve the same result:

if (text.startsWith('[new_ideas] '))
    text = text.replace('[new_ideas] ', '');

if (text.startsWith('[new_ideas] '))
    text = text.substring(12);

if (text.startsWith('[new_ideas] '))
    text = text.slice(12);

Regarding performance, the last 2 should be the fastest, but actual performance will depend on your target system. Careful benchmarking will show which is the fastest, but it is unlikely to make a difference in production code.

Note that if you do not care whether the substring appears at the start of the string, you can just write:

text = text.replace('[new_ideas] ', '');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM