web-dev-qa-db-fra.com

Méthode la plus rapide pour remplacer toutes les occurrences d'un caractère dans une chaîne

Quel est le moyen le plus rapide de remplacer toutes les occurrences d'une chaîne/d'un caractère dans une chaîne en JavaScript? Une while, une for- boucle, une expression régulière?

534
Anriëtte Myburgh

Le plus simple serait d’utiliser une expression régulière avec le drapeau g pour remplacer toutes les instances:

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

Ceci remplacera toutes les occurrences de foo par bar dans la chaîne str. Si vous avez juste une chaîne, vous pouvez la convertir en un objet RegExp comme ceci:

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

Essayez cette remplacement: 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);
} 

C'est très rapide et cela fonctionnera pour TOUTES ces conditions .__ que beaucoup d'autres échouent:

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

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

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

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

Faites-moi savoir si vous pouvez le casser, ou si vous avez quelque chose de mieux, mais assurez-vous qu'il peut passer ces 4 tests.

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

newString est maintenant 'Thas as a strang'

80
Sani Singh Huttunen

Aussi, vous pouvez essayer:

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

Rien que de penser à une question de vitesse, j’estime que l’exemple sensible au casse fourni dans le lien ci-dessus serait de loin la solution la plus rapide.

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 serait "Ceci est un test du système de diffusion d'urgence."

9
ADamienS

Vous pouvez utiliser les éléments suivants:

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

ou

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

Cela va remplacer tous les caractères qui ne sont pas des lettres ou des chiffres ((_)). Changez simplement la valeur de soulignement pour ce que vous voulez le remplacer. 

9
ssamuel68

Je pense que la vraie réponse est que cela dépend complètement de ce à quoi ressemblent vos entrées. J'ai créé un JsFiddle pour essayer un tas de ceux-ci et un couple de mon propre contre diverses entrées. Peu importe comment je regarde les résultats, je ne vois aucun gagnant clair.

  • RegExp n'était le plus rapide dans aucun des cas de test, mais ce n'était pas mal non plus. 
  • L'approche Split/Join semble la plus rapide pour les remplacements clairsemés.
  • Celui que j'ai écrit semble le plus rapide pour les petites entrées et les remplacements denses :

    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;
    }
    
8
Rick Velde

Utilisez l'objet Regex comme ceci

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

Il remplacera toutes les occurrences de " dans '

6
Neel Kamal

Je ne sais pas ce qui est le plus rapide, mais je sais ce qui est le plus lisible - c'est ce qui est le plus court et le plus simple. Même si c'est un peu plus lent que les autres solutions, il vaut la peine d'être utilisé.

Alors utilisez:

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

Et appréciez le bon code au lieu du plus rapide (enfin ... 1/100000 sec. N’est pas une différence) et moche. ;)

6
Crozin

J'ai essayé plusieurs de ces suggestions après avoir réalisé qu'une mise en œuvre que j'avais écrite à ce sujet, probablement il y a près de 10 ans, ne fonctionnait vraiment pas complètement (bug de production désagréable dans un système oublié depuis longtemps, n'est-ce pas toujours le cas?!) ... ce que j’ai remarqué, c’est que ceux que j’ai essayés (je ne les ai pas tous essayés) avaient le même problème que le mien, c’est-à-dire qu’ils ne remplaceraient pas TOUT cas, mais le premier, du moins pour mon cas test de obtenir "test .... txt" en "test.txt" en remplaçant ".." par "." ... peut-être ai-je manqué la situation tellement regex? Mais je m'égare ...

J'ai donc réécrit mon implémentation comme suit. C'est assez simple, bien que je suppose que ce n'est pas le plus rapide, mais je ne pense pas non plus que la différence comptera avec les moteurs JS modernes, à moins que vous ne le fassiez dans une boucle serrée, bien sûr, mais c'est toujours le cas pour n'importe quoi ...

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;

}

J'espère que ça aide quelqu'un!

5
Frank W. Zammetti
// 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;
};
2
MadHatter

Utilisez la méthode replace() de l'objet String.

Comme indiqué dans la réponse sélectionnée, le drapeau/g doit être utilisé dans l'expression régulière, afin de remplacer toutes les occurrences de la sous-chaîne de la chaîne.

2
Franci Penov

Je viens de coder un repère et de tester les 3 premières réponses. Il semble que pour les chaînes courtes (<500 caractères)
La troisième réponse la plus votée est plus rapide que la deuxième la plus votée.

Pour les longues chaînes (ajoutez ".repeat (300)" à la chaîne de test), la réponse 1 est rapide, suivie de la deuxième et de la troisième.

Note:

Ce qui précède s’applique aux navigateurs utilisant le moteur v8 (chrome/chrome, etc.).
Avec firefox (moteur SpiderMonkey), les résultats sont totalement différents
Vérifiez par vous-mêmes !! Firefox avec la troisième solution semble être
plus de 4,5 fois plus rapide que Chrome avec la première solution ... folle: 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>

Le test se déroulera pendant 10 secondes (+ 2 secondes) lorsque vous cliquez sur le bouton.

Mes résultats (sur le même 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 euh?

A pris la liberté d'ajouter plus de résultats de tests

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)
0
Zibri

@Gumbo ajoutant une réponse supplémentaire - 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)

D&EACUTE;MO

0
Surya R Praveen