简体   繁体   English

替换字符串中所有字符实例的最快方法

[英]Fastest method to replace all instances of a character in a string

What is the fastest way to replace all instances of a string/character in a string in JavaScript? 用JavaScript替换字符串中所有字符串/字符实例的最快方法是什么? A while , a for -loop, a regular expression? while ,一个for循环,一个正则表达式?

The easiest would be to use a regular expression with g flag to replace all instances: 最简单的方法是使用带有g标志的正则表达式替换所有实例:

str.replace(/foo/g, "bar")

This will replace all occurrences of foo with bar in the string str . 这将用字符串str bar替换所有出现的foo If you just have a string, you can convert it to a RegExp object like this: 如果只有字符串,可以将其转换为RegExp对象,如下所示:

var pattern = "foobar",
    re = new RegExp(pattern, "g");

Try this replaceAll: http://dumpsite.com/forum/index.php?topic=4.msg8#msg8 试试这个replaceAll: http ://dumpsite.com/forum/index.php?topic=4.msg8#msg8

String.prototype.replaceAll = function(str1, str2, ignore) 
{
    return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2);
} 

It is very fast, and it will work for ALL these conditions that many others fail on: 它非常快,并且适用于许多其他条件无法满足的所有这些条件:

"x".replaceAll("x", "xyz");
// xyz

"x".replaceAll("", "xyz");
// xyzxxyz

"aA".replaceAll("a", "b", true);
// bb

"Hello???".replaceAll("?", "!");
// Hello!!!

Let me know if you can break it, or you have something better, but make sure it can pass these 4 tests. 让我知道您是否可以打破它,或者您有更好的东西,但是请确保它可以通过这四个测试。

var mystring = 'This is a string';
var newString = mystring.replace(/i/g, "a");

newString now is 'Thas as a strang' newString现在是'Thas as strang'

您也可以尝试:

string.split('foo').join('bar');

You can use the following: 您可以使用以下内容:

newStr = str.replace(/[^a-z0-9]/gi, '_');

or 要么

newStr = str.replace(/[^a-zA-Z0-9]/g, '_');

This is going to replace all the character that are not letter or numbers to ('_'). 这会将所有不是字母或数字的字符替换为('_')。 Simple change the underscore value for whatever you want to replace it. 只需更改下划线值即可替换任何要替换的内容。

Just thinking about it from a speed issue I believe the case sensitive example provided in the link above would be by far the fastest solution. 从速度问题考虑一下,我相信上面链接中提供的区分大小写的示例将是迄今为止最快的解决方案。

var token = "\r\n";
var newToken = " ";
var oldStr = "This is a test\r\nof the emergency broadcasting\r\nsystem.";
newStr = oldStr.split(token).join(newToken);

newStr would be "This is a test of the emergency broadcast system." newStr将是“这是对紧急广播系统的测试”。

I think the real answer is that it completely depends on what your inputs look like. 我认为真正的答案是,这完全取决于您输入的内容。 I created a JsFiddle to try a bunch of these and a couple of my own against various inputs. 我创建了一个JsFiddle来尝试其中的一些以及我自己的一些反对各种输入的方法。 No matter how I look at the results, I see no clear winner. 无论我如何看待结果,都看不到明显的赢家。

  • RegExp wasn't the fastest in any of the test cases, but it wasn't bad either. RegExp并不是在所有测试用例中都最快的,但也不错。
  • Split/Join approach seems fastest for sparse replacements. 对于稀疏替换,拆分/合并方法似乎最快。
  • This one I wrote seems fastest for small inputs and dense replacements: 我写的这篇文章对于小投入和密集替换似乎最快:

     function replaceAllOneCharAtATime(inSource, inToReplace, inReplaceWith) { var output=""; var firstReplaceCompareCharacter = inToReplace.charAt(0); var sourceLength = inSource.length; var replaceLengthMinusOne = inToReplace.length - 1; for(var i = 0; i < sourceLength; i++){ var currentCharacter = inSource.charAt(i); var compareIndex = i; var replaceIndex = 0; var sourceCompareCharacter = currentCharacter; var replaceCompareCharacter = firstReplaceCompareCharacter; while(true){ if(sourceCompareCharacter != replaceCompareCharacter){ output += currentCharacter; break; } if(replaceIndex >= replaceLengthMinusOne) { i+=replaceLengthMinusOne; output += inReplaceWith; //was a match break; } compareIndex++; replaceIndex++; if(i >= sourceLength){ // not a match break; } sourceCompareCharacter = inSource.charAt(compareIndex) replaceCompareCharacter = inToReplace.charAt(replaceIndex); } replaceCompareCharacter += currentCharacter; } return output; } 

Use Regex object like this 像这样使用Regex对象

var regex = new RegExp('"', 'g'); str = str.replace(regex, '\\'');

It will replace all occurrence of " into ' . 它将替换所有出现的"'

I tried a number of these suggestions after realizing that an implementation I had written of this probably close to 10 years ago actually didn't work completely (nasty production bug in an long-forgotten system, isn't that always the way?!)... what I noticed is that the ones I tried (I didn't try them all) had the same problem as mine, that is, they wouldn't replace EVERY occurrence, only the first, at least for my test case of getting "test....txt" down to "test.txt" by replacing ".." with "."... maybe I missed so regex situation? 在意识到我大概在10年前写的一个实现实际上并不能完全正常工作后,我尝试了许多这样的建议(在一个长期被遗忘的系统中,讨厌的生产错误,不是总是这样吗?!) ...我注意到的是,我尝试过的(我没有全部尝试)与我的问题相同,也就是说,它们不会取代每次出现的情况,只有第一次出现,至少对于我的测试案例通过将“ ..”替换为“。”将“ test .... txt”降至“ test.txt” ...也许我错过了正则表达式的情况? But I digress... 但是我离题了...

So, I rewrote my implementation as follows. 因此,我将实现重写如下。 It's pretty darned simple, although I suspect not the fastest but I also don't think the difference will matter with modern JS engines, unless you're doing this inside a tight loop of course, but that's always the case for anything... 这很简单,虽然我怀疑不是最快的,但我也不认为现代JS引擎的区别会很重要,除非您当然是在一个紧密的循环中进行此操作,但是任何情况始终如此...

function replaceSubstring(inSource, inToReplace, inReplaceWith) {

  var outString = inSource;
  while (true) {
    var idx = outString.indexOf(inToReplace);
    if (idx == -1) {
      break;
    }
    outString = outString.substring(0, idx) + inReplaceWith +
      outString.substring(idx + inToReplace.length);
  }
  return outString;

}

Hope that helps someone! 希望能对某人有所帮助!

What's the fastest I don't know, but I know what's the most readable - that what's shortest and simplest. 我不知道最快的是什么,但是我知道最可读的是-最短和最简单的东西。 Even if it's a little bit slower than other solution it's worth to use. 即使它比其他解决方案慢一点,也值得使用。

So use: 因此使用:

 "string".replace("a", "b");
 "string".replace(/abc?/g, "def");

And enjoy good code instead of faster (well... 1/100000 sec. is not a difference) and ugly one. 享受更好的代码而不是更快(好吧... 1/100000秒没什么区别)和丑陋的代码。 ;) ;)

// Find, Replace, Case
// i.e "Test to see if this works? (Yes|No)".replaceAll('(Yes|No)', 'Yes!');
// i.e.2 "Test to see if this works? (Yes|No)".replaceAll('(yes|no)', 'Yes!', true);
String.prototype.replaceAll = function(_f, _r, _c){ 

  var o = this.toString();
  var r = '';
  var s = o;
  var b = 0;
  var e = -1;
  if(_c){ _f = _f.toLowerCase(); s = o.toLowerCase(); }

  while((e=s.indexOf(_f)) > -1)
  {
    r += o.substring(b, b+e) + _r;
    s = s.substring(e+_f.length, s.length);
    b += e+_f.length;
  }

  // Add Leftover
  if(s.length>0){ r+=o.substring(o.length-s.length, o.length); }

  // Return New String
  return r;
};

Use the replace() method of the String object. 使用String对象的replace()方法。

As mentioned in the selected answer, the /g flag should be used in the regex, in order to replace all instances of the substring in the string. 如所选答案中所述,/ g标志应在正则表达式中使用,以便替换字符串中子字符串的所有实例。

I just coded a benchmark and tested the first 3 answers. 我只是编写了一个基准并测试了前三个答案。 It seems that for short strings (<500 characters) 似乎对于短字符串(<500个字符)
the third most voted answer is faster than the second most voted one. 第三投票最多的答案要快于第二投票最多的答案。

For long strings (add ".repeat(300)" to the test string) the faster is answer 1 followed by the second and the third. 对于长字符串(将“ .repeat(300)”添加到测试字符串),最快的是答案1,然后是第二个和第三个。

Note: 注意:

The above is true for browsers using v8 engine (chrome/chromium etc). 以上适用于使用v8引擎(铬/铬等)的浏览器。
With firefox (SpiderMonkey engine) the results are totally different 使用firefox(SpiderMonkey引擎),结果完全不同
Check for yourselves!! 自己检查!! Firefox with the third solution seems to be Firefox与第三个解决方案似乎是
more than 4.5 times faster than Chrome with the first solution... crazy :D 第一个解决方案的速度比Chrome快4.5倍...疯狂:D

 function log(data) { document.getElementById("log").textContent += data + "\\n"; } benchmark = (() => { time_function = function(ms, f, num) { var z; var t = new Date().getTime(); for (z = 0; ((new Date().getTime() - t) < ms); z++) f(num); return (z / ms) } // returns how many times the function was run in "ms" milliseconds. function benchmark() { function compare(a, b) { if (a[1] > b[1]) { return -1; } if (a[1] < b[1]) { return 1; } return 0; } // functions function replace1(s) { s.replace(/foo/g, "bar") } String.prototype.replaceAll2 = function(_f, _r){ var o = this.toString(); var r = ''; var s = o; var b = 0; var e = -1; // if(_c){ _f = _f.toLowerCase(); s = o.toLowerCase(); } while((e=s.indexOf(_f)) > -1) { r += o.substring(b, b+e) + _r; s = s.substring(e+_f.length, s.length); b += e+_f.length; } // Add Leftover if(s.length>0){ r+=o.substring(o.length-s.length, o.length); } // Return New String return r; }; String.prototype.replaceAll = function(str1, str2, ignore) { return this.replace(new RegExp(str1.replace(/([\\/\\,\\!\\\\\\^\\$\\{\\}\\[\\]\\(\\)\\.\\*\\+\\?\\|\\<\\>\\-\\&])/g, "\\\\$&"), (ignore ? "gi" : "g")), (typeof(str2) == "string") ? str2.replace(/\\$/g, "$$$$") : str2); } function replace2(s) { s.replaceAll("foo", "bar") } function replace3(s) { s.split('foo').join('bar'); } function replace4(s) { s.replaceAll2("foo", "bar") } funcs = [ [replace1, 0], [replace2, 0], [replace3, 0], [replace4, 0] ]; funcs.forEach((ff) => { console.log("Benchmarking: " + ff[0].name); ff[1] = time_function(2500, ff[0], "foOfoobarBaR barbarfoobarf00".repeat(10)); console.log("Score: " + ff[1]); }) return funcs.sort(compare); } return benchmark; })() log("Starting benchmark...\\n"); res = benchmark(); console.log("Winner: " + res[0][0].name + " !!!"); count = 1; res.forEach((r) => { log((count++) + ". " + r[0].name + " score: " + Math.floor(10000 * r[1] / res[0][1]) / 100 + ((count == 2) ? "% *winner*" : "% speed of winner.") + " (" + Math.round(r[1] * 100) / 100 + ")"); }); log("\\nWinner code:\\n"); log(res[0][0].toString()); 
 <textarea rows="50" cols="80" style="font-size: 16; resize:none; border: none;" id="log"></textarea> 

The test will run for 10s (+2s) as you click the button. 单击按钮后,测试将运行10秒(+ 2s)。

My results (on the same pc): 我的结果(在同一台PC上):

Chrome/Linux Ubuntu 64:
1. replace1 score: 100% *winner* (766.18)
2. replace4 score: 99.07% speed of winner. (759.11)
3. replace3 score: 68.36% speed of winner. (523.83)
4. replace2 score: 59.35% speed of winner. (454.78)

Firefox/Linux Ubuntu 64
1. replace3 score: 100% *winner* (3480.1)
2. replace1 score: 13.06% speed of winner. (454.83)
3. replace4 score: 9.4% speed of winner. (327.42)
4. replace2 score: 4.81% speed of winner. (167.46)

Nice mess uh? 好乱吧?

Took the liberty of adding more test results 自由添加更多测试结果

Chrome/Windows 10
1. replace1 score: 100% *winner* (742.49)
2. replace4 score: 85.58% speed of winner. (635.44)
3. replace2 score: 54.42% speed of winner. (404.08)
4. replace3 score: 50.06% speed of winner. (371.73)

Firefox/Windows 10
1. replace3 score: 100% *winner* (2645.18)
2. replace1 score: 30.77% speed of winner. (814.18)
3. replace4 score: 22.3% speed of winner. (589.97)
4. replace2 score: 12.51% speed of winner. (331.13)

Edge/Windows 10
1. replace1 score: 100% *winner* (1251.24)
2. replace2 score: 46.63% speed of winner. (583.47)
3. replace3 score: 44.42% speed of winner. (555.92)
4. replace4 score: 20% speed of winner. (250.28)

Chrome on Galaxy Note 4 Chrome on Galaxy Note 4

1. replace4 score: 100% *winner* (99.82)
2. replace1 score: 91.04% speed of winner. (90.88)
3. replace3 score: 70.27% speed of winner. (70.15)
4. replace2 score: 38.25% speed of winner. (38.18)

@Gumbo adding extra answer - user.email.replace(/foo/gi,"bar"); @Gumbo添加了额外的答案-user.email.replace(/ foo / gi,“ bar”);

/foo/g - Refers to the all string to replace matching the case sensitive

/foo/gi - Refers to the without case sensitive and replace all For Eg: (Foo, foo, FoO, fOO)

DEMO 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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