JavaScript: remplace la dernière occurrence de texte dans une chaîne
Voir mon extrait de code ci-dessous:
var list = ['one', 'two', 'three', 'four'];
var str = 'one two, one three, one four, one';
for ( var i = 0; i < list.length; i++)
{
if (str.endsWith(list[i])
{
str = str.replace(list[i], 'finish')
}
}
Je veux remplacer la dernière occurrence du mot one par le mot finish dans la chaîne, ce que j'ai ne fonctionnera pas car la méthode replace ne remplacera que la première occurrence de celui-ci. Est-ce que quelqu'un sait comment je peux modifier cet extrait de sorte qu'il ne remplace que la dernière instance de ' one '
12 réponses
Eh bien, si la chaîne se termine vraiment par le motif, vous pouvez faire ceci:
str = str.replace(new RegExp(list[i] + '$'), 'finish');
Vous pouvez utiliser String#lastIndexOf
pour trouver la dernière occurrence du mot, puis String#substring
et la concaténation de construire la chaîne de remplacement.
n = str.lastIndexOf(list[i]);
if (n >= 0 && n + list[i].length >= str.length) {
str = str.substring(0, n) + "finish";
}
...ou le long de ces lignes.
Je sais que c'est idiot, mais je me sens créatif ce matin:
'one two, one three, one four, one'
.split(' ') // array: ["one", "two,", "one", "three,", "one", "four,", "one"]
.reverse() // array: ["one", "four,", "one", "three,", "one", "two,", "one"]
.join(' ') // string: "one four, one three, one two, one"
.replace(/one/, 'finish') // string: "finish four, one three, one two, one"
.split(' ') // array: ["finish", "four,", "one", "three,", "one", "two,", "one"]
.reverse() // array: ["one", "two,", "one", "three,", "one", "four,", "finish"]
.join(' '); // final string: "one two, one three, one four, finish"
Donc, vraiment, tout ce que vous devez faire est d'ajouter cette fonction au prototype de chaîne:
String.prototype.replaceLast = function (what, replacement) {
return this.split(' ').reverse().join(' ').replace(new RegExp(what), replacement).split(' ').reverse().join(' ');
};
Ensuite, exécutez-le comme suit:
str = str.replaceLast('one', 'finish');
une limitation que vous devriez savoir est que, puisque la fonction est divisée par espace, vous probablement ne pouvez pas trouver / remplacer quoi que ce soit par un espace.
En fait, maintenant que j'y pense, vous pourriez contourner le problème de l'espace en divisant avec un vide jeton.
String.prototype.reverse = function () {
return this.split('').reverse().join('');
};
String.prototype.replaceLast = function (what, replacement) {
return this.reverse().replace(new RegExp(what.reverse()), replacement.reverse()).reverse();
};
str = str.replaceLast('one', 'finish');
Pas aussi élégant que les réponses regex ci-dessus, mais plus facile à suivre pour les moins avertis parmi nous:
function removeLastInstance(badtext, str) {
var charpos = str.lastIndexOf(badtext);
if (charpos<0) return str;
ptone = str.substring(0,charpos);
pttwo = str.substring(charpos+(badtext.length));
return (ptone+pttwo);
}
Je me rends compte que c'est probablement plus lent et plus inutile que les exemples regex, mais je pense que cela pourrait être utile comme illustration de la façon dont les manipulations de chaînes peuvent être effectuées. (Il peut aussi être condensé un peu, mais encore une fois, je voulais que chaque étape soit claire.)
Pensé que je répondrais ici puisque cela est apparu en premier dans ma recherche Google et il n'y a pas de réponse (en dehors de la réponse créative de Matt :)) qui remplace génériquement la dernière occurrence d'une chaîne de caractères lorsque le texte à remplacer peut ne pas être à la fin de la chaîne.
if (!String.prototype.replaceLast) {
String.prototype.replaceLast = function(find, replace) {
var index = this.lastIndexOf(find);
if (index >= 0) {
return this.substring(0, index) + replace + this.substring(index + find.length);
}
return this.toString();
};
}
var str = 'one two, one three, one four, one';
// outputs: one two, one three, one four, finish
console.log(str.replaceLast('one', 'finish'));
// outputs: one two, one three, one four; one
console.log(str.replaceLast(',', ';'));
Voici une méthode qui utilise uniquement le fractionnement et la jointure. C'est un peu plus lisible, alors j'ai pensé que ça valait la peine d'être partagé:
String.prototype.replaceLast = function (what, replacement) {
var pcs = this.split(what);
var lastPc = pcs.pop();
return pcs.join(what) + replacement + lastPc;
};
Ne pourriez-vous pas simplement inverser la chaîne et remplacer uniquement la première occurrence du motif de recherche inversé? Je suis en train de penser . . .
var list = ['one', 'two', 'three', 'four'];
var str = 'one two, one three, one four, one';
for ( var i = 0; i < list.length; i++)
{
if (str.endsWith(list[i])
{
var reversedHaystack = str.split('').reverse().join('');
var reversedNeedle = list[i].split('').reverse().join('');
reversedHaystack = reversedHaystack.replace(reversedNeedle, 'hsinif');
str = reversedHaystack.split('').reverse().join('');
}
}
À l'Ancienne et code mais efficace que possible:
function replaceLast(origin,text){
textLenght = text.length;
originLen = origin.length
if(textLenght == 0)
return origin;
start = originLen-textLenght;
if(start < 0){
return origin;
}
if(start == 0){
return "";
}
for(i = start; i >= 0; i--){
k = 0;
while(origin[i+k] == text[k]){
k++
if(k == textLenght)
break;
}
if(k == textLenght)
break;
}
//not founded
if(k != textLenght)
return origin;
//founded and i starts on correct and i+k is the first char after
end = origin.substring(i+k,originLen);
if(i == 0)
return end;
else{
start = origin.substring(0,i)
return (start + end);
}
}
Si la vitesse est importante, utilisez ceci:
/**
* Replace last occurrence of a string with another string
* x - the initial string
* y - string to replace
* z - string that will replace
*/
function replaceLast(x, y, z){
var a = x.split("");
var length = y.length;
if(x.lastIndexOf(y) != -1) {
for(var i = x.lastIndexOf(y); i < x.lastIndexOf(y) + length; i++) {
if(i == x.lastIndexOf(y)) {
a[i] = z;
}
else {
delete a[i];
}
}
}
return a.join("");
}
C'est plus rapide que D'utiliser RegExp.
Je suggère d'utiliser le paquetreplace-last npm.
var str = 'one two, one three, one four, one';
var result = replaceLast(str, 'one', 'finish');
console.log(result);
<script src="https://unpkg.com/replace-last@latest/replaceLast.js"></script>
Cela fonctionne pour les remplacements de chaînes et de regex.
, Une réponse simple, sans regex serait:
str = str.substr(0, str.lastIndexOf(list[i])) + 'finish'