Development Tip

문자열에서 문자의 모든 인스턴스를 바꾸는 가장 빠른 방법

yourdevel 2020. 10. 2. 23:25
반응형

문자열에서 문자의 모든 인스턴스를 바꾸는 가장 빠른 방법


JavaScript의 문자열에서 문자열 / 문자의 모든 인스턴스를 대체하는 가장 빠른 방법은 무엇입니까? A while, for루프, 정규 표현식?


가장 쉬운 방법은 g플래그가 있는 정규식을 사용하여 모든 인스턴스를 대체하는 것입니다.

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

이렇게하면 문자열에서 모든 항목이 foobar바뀝니다 str. 문자열 만있는 경우 다음과 같이 RegExp 개체로 변환 할 수 있습니다.

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

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

매우 빠르며 다른 많은 사람들이 실패하는 이러한 모든 조건에서 작동합니다.

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

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

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

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

깨뜨릴 수 있는지 또는 더 나은 것이 있는지 알려주십시오. 그러나이 4 가지 테스트를 통과 할 수 있는지 확인하십시오.


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

newString은 이제 'Thas as a strang'입니다.


또한 시도해 볼 수 있습니다.

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

다음을 사용할 수 있습니다.

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

또는

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

이것은 문자 나 숫자가 아닌 모든 문자를 ( '_')로 대체합니다. 대체하려는 항목의 밑줄 값을 간단히 변경하십시오.


속도 문제에서 생각해 보면 위의 링크에 제공된 대소 문자 구분 예제가 가장 빠른 솔루션이라고 생각합니다.

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은 "이것은 비상 방송 시스템의 테스트입니다."입니다.


진짜 대답은 그것이 당신의 입력이 어떻게 생겼는지에 완전히 달려 있다는 것입니다. 나는 JsFiddle만들어서 다양한 입력에 대해 이것들과 몇 가지를 시도했습니다. 결과를 어떻게 보더라도 확실한 승자는 없습니다.

  • RegExp는 어떤 테스트 케이스에서도 가장 빠르지는 않았지만 나쁘지 않았습니다.
  • 분할 / 결합 접근 방식은 희소 교체의 경우 가장 빠릅니다.
  • 내가 쓴 이것은 작은 입력과 고밀도 대체에 대해 가장 빠른 것 같습니다.

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

다음과 같이 Regex 개체를 사용하십시오.

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

의 모든 항목을 "대체합니다 '.


가장 빠른 것이 무엇인지 모르겠지만 가장 읽기 쉬운 것이 무엇인지 알고 있습니다. 가장 짧고 간단한 것이 무엇인지 압니다. 다른 솔루션보다 조금 느리더라도 사용할 가치가 있습니다.

따라서 다음을 사용하십시오.

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

그리고 더 빠르고 (음 ... 1/100000 초는 차이가 없습니다) 못생긴 코드 대신 좋은 코드를 즐기십시오. ;)


10 년 전에 작성한 구현이 실제로 완전히 작동하지 않는다는 사실을 깨닫고 이러한 제안을 여러 번 시도해 보았습니다 (오래 잊혀진 시스템의 불쾌한 프로덕션 버그가 항상 그런 것은 아닙니까?!). ... 내가 알아 차린 것은 내가 시도한 것 (모두 시도하지 않았 음)이 내 것과 동일한 문제를 가지고 있다는 것입니다. 즉, 그들은 모든 발생을 대체하지 않을 것입니다. ".."를 "."로 대체하여 "test .... txt"를 "test.txt"로 가져 오는 중 ... 어쩌면 정규식 상황을 놓쳤을까요? 하지만 나는 빗나 갔다 ...

그래서 다음과 같이 구현을 다시 작성했습니다. 그것은 매우 간단합니다. 비록 가장 빠르지는 않다고 생각하지만, 물론 타이트한 루프 안에서 이것을 수행하지 않는 한, 현대 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;

}

누군가에게 도움이되기를 바랍니다!


// 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;
};

개체 replace()방법을 사용하십시오 String.

선택한 답변에서 언급했듯이 문자열에서 하위 문자열의 모든 인스턴스 를 바꾸려면 정규식에서 / g 플래그를 사용해야 합니다.


방금 벤치 마크를 코딩하고 처음 3 개의 답변을 테스트했습니다. 짧은 문자열 (<500 자)의
경우 세 번째로 많이 득표 한 답변이 두 번째로 많이 득표 한 답변보다 빠릅니다.

긴 문자열 (테스트 문자열에 ".repeat (300)"추가)의 경우 답 1 다음에 두 번째와 세 번째가 더 빠릅니다.

노트 :

위의 내용은 v8 엔진 (크롬 / 크롬 등)을 사용하는 브라우저에 해당됩니다.
파이어 폭스 (SpiderMonkey 엔진)를 사용하면 결과가 완전히 다릅니다.
스스로 확인하십시오 !! 세 번째 솔루션을 사용하는 Firefox
는 첫 번째 솔루션을 사용하는 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>

버튼을 클릭하면 테스트가 10 초 (+2 초) 동안 실행됩니다.

내 결과 (같은 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)

엉망진창 어?

더 많은 테스트 결과를 추가 할 자유를 얻었습니다.

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)

Galaxy Note 4의 Chrome

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 추가 답변 추가-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)

데모

참고 URL : https://stackoverflow.com/questions/2116558/fastest-method-to-replace-all-instances-of-a-character-in-a-string

반응형