【问题标题】:What's the fastest way to remove a string from the beginning of another string in Javascript?从Javascript中另一个字符串的开头删除一个字符串的最快方法是什么?
【发布时间】:2020-12-05 19:11:14
【问题描述】:

我正在比较从另一个字符串中删除第一次出现的字符串的不同方法:数组拆分与正则表达式替换。

假设我有一个像这样的字符串:

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

我只想从字符串中删除第一次出现的[new_ideas](不是第二次)。

最快、最有效的方法是什么?

到目前为止,我有:

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)

这是否足够快或有更好的方法来做到这一点?例如,将replace 与正则表达式一起使用?还是在这种情况下忽略了生产力提升?

【问题讨论】:

  • 只有你才能说它是否足够快。要看!一般来说没问题。我想它比正则表达式更快
  • 在替换原字符串时保持不变。
  • "或者在这种情况下是否忽略了生产力的提升?" - 是的,几乎可以肯定。但如果您真的很在意,您必须自己进行基准测试(使用您的真实数据,在您的真实环境中)。
  • 我认为您的split 解决方案甚至都不正确。当要替换的字符串没有或不止一次出现时,它不会执行您想要的操作。您正在寻找text.replace(/^\[new_ideas\] /, '')text.startsWith('[new_ideas] ') ? text.slice('[new_ideas] '.length) : text

标签: javascript arrays string performance


【解决方案1】:

split 将查找所有出现的事件,除非您指定最大值;它在第二个参数中提供: text.split('[new_ideas] ', 2)[1]。它还将为每个条目作为数组创建内存开销。但是,您可以简单地使用 replace 而无需任何正则表达式:

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

由于replace 的运作方式,这只会删除第一个匹配项(查看文档)。

【讨论】:

  • 请注意,没有正则表达式的replace 将替换第一次出现,无论它是否恰好在开头。
  • OP 明确表示他们想替换 first
  • 是的,他们只想替换一个,但标题也有资格将它放在开头。
  • 不一定,而是表示第一个从头开始
【解决方案2】:

对于提供的输入,它似乎没有太大的区别。您可以在本地或这里自己尝试:https://jsbench.github.io/

对于较长的字符串,简单的文本替换应该会更好,但问题是:这有关系吗?这是一个特定于应用程序的问题。

下面是 100 万次迭代的比较,您自己判断操作是否经常执行,足以保证性能讨论。

此基准测试未生效的是内存占用。结果也可能取决于实际输入,因此 YMMV。

下面的代码给出了以下基准测试结果(在 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') 
  }

}

【讨论】:

  • OP 只想替换一个匹配项并且只替换字符串的开头,所以你会使用 replaceAll!?
  • 刚刚添加它以可视化replacereplaceAll 之间的性能差异,因为第一个将在第一个匹配时停止,而后者将一直持续到字符串的末尾。
【解决方案3】:

我很惊讶没有人提出一个简单的substr 替代方案:

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);

这似乎是最快的解决方案:

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

您甚至可以通过硬编码length 结果(如果适用)来进一步压缩它,例如:

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

无论如何,我非常怀疑这会对现实生活中的应用程序产生可衡量的变化。因此,请选择您更舒适或更易于阅读和维护的选项。

【讨论】:

    【解决方案4】:

    问题不明确:

    1. 在 Javascript 中从另一个字符串的开头删除一个字符串的最快方法是什么?

    2. 我正在比较从另一个字符串中删除第一次出现的字符串的不同方法

    这些语句并不相同:您的意思是只删除另一个字符串开头的字符串还是只删除第一次出现的字符串?

    您提出的String.prototype.split 解决方案无法按编码工作,您必须传递第二个参数来限制将拆分限制为的部分数量。它似乎适用于您的示例的原因是重复的字符串是 "[new_ideas]" 但您指定 "[new_ideas] " 带有一个不重复的尾随空格。

    去掉字符串可以这样写:

    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)
    

    请注意,如果字符串中没有 "[new ideas] " 的匹配项,text 将是未定义的。因此,您应该首先测试与text.includes('[new_ideas] ') 的匹配,或者检查字符串是否以text.startsWith('[new_ideas] ') 的子字符串开头。

    有更简单的方法可以达到相同的结果:

    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);
    

    关于性能,最后 2 个应该是最快的,但实际性能将取决于您的目标系统。仔细的基准测试将显示哪个是最快的,但不太可能对生产代码产生影响。

    注意,如果你不关心子字符串是否出现在字符串的开头,你可以直接写:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-14
      • 2011-08-14
      • 2023-02-18
      • 2017-05-19
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      相关资源
      最近更新 更多