Zobacz mój fragment kodu poniżej:
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')
}
}
Chcę zastąpić ostatnie wystąpienie słowa jeden słowem finish w ciągu, to co mam nie zadziała, ponieważ metoda replace zamieni tylko pierwsze jego wystąpienie. Czy ktoś wie, jak mogę zmienić ten fragment, tak aby zastępował tylko ostatnie wystąpienie „jeden”
javascript
string
replace
Litość
źródło
źródło
new RegExp(string)
) i wbudowana składnia (/something/
). Nie potrzebujesz znaków „/”, gdy używasz konstruktora RegExp.` - things like
+,
*,
? `, Nawiasów, nawiasów kwadratowych, może innych rzeczy.Możesz użyć,
String#lastIndexOf
aby znaleźć ostatnie wystąpienie słowa, a następnieString#substring
i połączyć w celu zbudowania ciągu zastępczego.n = str.lastIndexOf(list[i]); if (n >= 0 && n + list[i].length >= str.length) { str = str.substring(0, n) + "finish"; }
... lub wzdłuż tych linii.
źródło
Wiem, że to głupie, ale dziś rano czuję się kreatywny:
'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"
Więc tak naprawdę wszystko, co musiałbyś zrobić, to dodać tę funkcję do prototypu String:
String.prototype.replaceLast = function (what, replacement) { return this.split(' ').reverse().join(' ').replace(new RegExp(what), replacement).split(' ').reverse().join(' '); };
Następnie uruchom to tak:
str = str.replaceLast('one', 'finish');
Jedynym ograniczeniem, które powinieneś wiedzieć, jest to, że ponieważ funkcja jest dzielona przez spację, prawdopodobnie nie możesz znaleźć / zastąpić niczego spacją.Właściwie, teraz, kiedy o tym myślę, możesz obejść problem „przestrzeni”, rozdzielając go pustym tokenem.
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');
źródło
Nie tak eleganckie, jak powyższe wyrażenie regularne, ale łatwiejsze do zrozumienia dla mniej doświadczonych spośród nas:
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); }
Zdaję sobie sprawę, że jest to prawdopodobnie wolniejsze i bardziej marnotrawne niż przykłady wyrażeń regularnych, ale myślę, że może być pomocne jako ilustracja tego, jak można wykonać manipulacje na ciągach. (Można to też trochę skondensować, ale znowu chciałem, aby każdy krok był jasny.)
źródło
Oto metoda, która wykorzystuje tylko dzielenie i łączenie. Jest trochę bardziej czytelny, więc pomyślałem, że warto się nim podzielić:
String.prototype.replaceLast = function (what, replacement) { var pcs = this.split(what); var lastPc = pcs.pop(); return pcs.join(what) + replacement + lastPc; };
źródło
what
w ogóle nie zawiera . np.'foo'.replaceLast('bar'); // 'barfoo'
Pomyślałem, że odpowiem tutaj, ponieważ pojawiło się to jako pierwsze w mojej wyszukiwarce Google i nie ma odpowiedzi (poza twórczą odpowiedzią Matta :)), która generalnie zastępuje ostatnie wystąpienie ciągu znaków, gdy tekst do zastąpienia może nie znajdować się na końcu sznurka.
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(',', ';'));
źródło
Prosta odpowiedź bez wyrażenia regularnego brzmiałaby:
str = str.substr(0, str.lastIndexOf(list[i])) + 'finish'
źródło
Czy nie mógłbyś po prostu odwrócić łańcucha i zamienić tylko pierwszego wystąpienia odwróconego wzorca wyszukiwania? Myślę . . .
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(''); } }
źródło
Jeśli ważna jest prędkość, użyj tego:
/** * 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(""); }
To szybsze niż użycie RegExp.
źródło
Prostym rozwiązaniem byłoby użycie metody podciągowej. Ponieważ łańcuch kończy się elementem listy, możemy użyć string.length i obliczyć indeks końcowy dla podłańcucha bez użycia
lastIndexOf
metodystr = str.substring(0, str.length - list[i].length) + "finish"
źródło
Staroświecki i duży kod, ale wydajny, jak to tylko możliwe:
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); } }
źródło
Nie podobała mi się żadna z powyższych odpowiedzi i wymyśliłem poniższe
function replaceLastOccurrenceInString(input, find, replaceWith) { if (!input || !find || !replaceWith || !input.length || !find.length || !replaceWith.length) { // returns input on invalid arguments return input; } const lastIndex = input.lastIndexOf(find); if (lastIndex < 0) { return input; } return input.substr(0, lastIndex) + replaceWith + input.substr(lastIndex + find.length); }
Stosowanie:
const input = 'ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty'; const find = 'teen'; const replaceWith = 'teenhundred'; const output = replaceLastOccurrenceInString(input, find, replaceWith); console.log(output); // output: ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteenhundred twenty
Mam nadzieję, że to pomoże!
źródło
Sugerowałbym użycie pakietu replace-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>
Działa to w przypadku zamiany ciągów i wyrażeń regularnych.
źródło
str = (str + '?').replace(list[i] + '?', 'finish');
źródło