Jak mogę wstawić ciąg pod określony indeks innego ciągu?
var txt1 = "foo baz"
Załóżmy, że chcę wstawić „pasek” po „foo”, jak mogę to osiągnąć?
Myślałem o tym substring()
, ale musi istnieć prostszy, bardziej bezpośredni sposób.
Jak mogę wstawić ciąg pod określony indeks innego ciągu?
var txt1 = "foo baz"
Załóżmy, że chcę wstawić „pasek” po „foo”, jak mogę to osiągnąć?
Myślałem o tym substring()
, ale musi istnieć prostszy, bardziej bezpośredni sposób.
Odpowiedzi:
Możesz stworzyć własny splice()
ciąg w String.
if (!String.prototype.splice) {
/**
* {JSDoc}
*
* The splice() method changes the content of a string by removing a range of
* characters and/or adding new characters.
*
* @this {String}
* @param {number} start Index at which to start changing the string.
* @param {number} delCount An integer indicating the number of old chars to remove.
* @param {string} newSubStr The String that is spliced in.
* @return {string} A new string with the spliced substring.
*/
String.prototype.splice = function(start, delCount, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
};
}
String.prototype.splice = function(idx, rem, str) {
return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};
var result = "foo baz".splice(4, 0, "bar ");
document.body.innerHTML = result; // "foo bar baz"
EDYCJA: Zmodyfikowano, aby zapewnić, że rem
jest to wartość bezwzględna.
slice
rozwiązanie jest lepsze i prostsze. (Splot jest destrukcyjny, plasterek nie, i lepiej unikać modyfikowania „obiektów, których nie znasz”). To rozwiązanie absolutnie nie powinno być pierwszą widoczną odpowiedzią, nawet jeśli w tamtym czasie mogło mieć sens.
my_array[my_array.length] = item
zamiast tego my_array.push(item)
?
splice
w tej sprawie; rzeczywiście ciągi są niezmienne. Z tego powodu myślę, że splice
jest to zły wybór słów kluczowych. Moje główne zastrzeżenie dotyczy arbitralnego rozszerzenia prototypów, chyba że są to standardowe opakowania wielokrotne.
Wstawianie do określonego indeksu (zamiast, powiedzmy, pierwszego znaku spacji), musi używać odcinania / podciągania łańcucha:
var txt2 = txt1.slice(0, 3) + "bar" + txt1.slice(3);
substring
byłoby dobrze tutaj. slice
Ogólnie wolę, ponieważ jest bardziej elastyczny (np "foo baz".slice(1, -2)
. Wskaźniki ujemne ). Jest również nieco krótszy, dla tego, co jest warte.
`${txt1.slice(0,3)}bar${txt1.slice(3)}`
delete
funkcji opisanej powyżej; najlepsza odpowiedź ...
Oto metoda, którą napisałem, która zachowuje się jak wszystkie inne języki programowania:
String.prototype.insert = function(index, string) {
if (index > 0)
{
return this.substring(0, index) + string + this.substring(index, this.length);
}
return string + this;
};
//Example of use:
var something = "How you?";
something = something.insert(3, " are");
console.log(something)
{}
do bloków if-else.
else
jest zbędne.
Po prostu wykonaj następującą funkcję:
function insert(str, index, value) {
return str.substr(0, index) + value + str.substr(index);
}
a następnie użyj go w ten sposób:
alert(insert("foo baz", 4, "bar "));
Wyjście: foo bar baz
Zachowuje się dokładnie tak, jak C # (Sharp) String.Insert (int startIndex, wartość ciągu).
UWAGA: Ta funkcja wstawiania wstawia wartość ciągu (trzeci parametr) przed określonym indeksem całkowitym (drugi parametr) w ciągu str (pierwszy parametr), a następnie zwraca nowy ciąg bez zmiany str !
AKTUALIZACJA 2016: Oto kolejna funkcja prototypowa dla zabawy (ale poważniejszej!) Oparta na RegExp
podejściu jednowierszowym (z obsługą przedpłaconą undefined
lub ujemną index
):
/**
* Insert `what` to string at position `index`.
*/
String.prototype.insert = function(what, index) {
return index > 0
? this.replace(new RegExp('.{' + index + '}'), '$&' + what)
: what + this;
};
console.log( 'foo baz'.insert('bar ', 4) ); // "foo bar baz"
console.log( 'foo baz'.insert('bar ') ); // "bar foo baz"
Poprzednie (powrót do 2012 r.) Rozwiązanie „ tylko dla zabawy” :
var index = 4,
what = 'bar ';
'foo baz'.replace(/./g, function(v, i) {
return i === index - 1 ? v + what : v;
}); // "foo bar baz"
Jeśli ktoś szuka sposobu na wstawienie tekstu w wielu indeksach w ciągu, wypróbuj to:
String.prototype.insertTextAtIndices = function(text) {
return this.replace(/./g, function(character, index) {
return text[index] ? text[index] + character : character;
});
};
Na przykład możesz użyć tego, aby wstawić <span>
tagi w określonych przesunięciach w ciągu:
var text = {
6: "<span>",
11: "</span>"
};
"Hello world!".insertTextAtIndices(text); // returns "Hello <span>world</span>!"
6: "<span>"
mówi: w indeksie 6 wstaw tekst „<span>”. Czy mówisz, że chcesz użyć wartości zmiennej całkowitej jako indeksu wstawiania? W takim przypadku spróbuj czegoś takiegovar a=6, text = {}; text[a] = "<span>";
Zasadniczo robi to, co robi @ Bass33, z wyjątkiem tego, że daję również opcję użycia indeksu ujemnego do liczenia od końca. Coś w rodzaju metody substr pozwala.
// use a negative index to insert relative to the end of the string.
String.prototype.insert = function (index, string) {
var ind = index < 0 ? this.length + index : index;
return this.substring(0, ind) + string + this.substring(ind, this.length);
};
Przypadek użycia: powiedzmy, że masz obrazy w pełnym rozmiarze przy użyciu konwencji nazewnictwa, ale nie możesz zaktualizować danych, aby podać także adresy URL miniatur.
var url = '/images/myimage.jpg';
var thumb = url.insert(-4, '_thm');
// result: '/images/myimage_thm.jpg'
Biorąc pod uwagę twój obecny przykład, możesz osiągnąć wynik przez jedno z nich
var txt2 = txt1.split(' ').join(' bar ')
lub
var txt2 = txt1.replace(' ', ' bar ');
ale biorąc pod uwagę, że możesz przyjąć takie założenia, równie dobrze możesz przejść bezpośrednio do przykładu Gullena.
W sytuacji, w której naprawdę nie możesz przyjąć żadnych innych założeń niż oparte na indeksie znaków, naprawdę wybrałbym rozwiązanie dla substringu.
my_string = "hello world";
my_insert = " dear";
my_insert_location = 5;
my_string = my_string.split('');
my_string.splice( my_insert_location , 0, my_insert );
my_string = my_string.join('');
Wiem, że to stary wątek, ale tutaj jest naprawdę skuteczne podejście.
var tn = document.createTextNode("I am just to help")
t.insertData(10, "trying");
Wspaniałe jest to, że wymusza zawartość węzła. Więc jeśli ten węzeł był już w DOM, nie musiałbyś używać żadnych selektorów zapytań ani aktualizować tekstu wewnętrznego. Zmiany odzwierciedlą się ze względu na jego wiążące.
Jeśli potrzebujesz łańcucha, po prostu uzyskaj dostęp do właściwości treści tekstowej węzła.
tn.textContent
#=> "I am just trying to help"
Możemy użyć zarówno metody substring, jak i slice.
String.prototype.customSplice = function (index, absIndex, string) {
return this.slice(0, index) + string+ this.slice(index + Math.abs(absIndex));
};
String.prototype.replaceString = function (index, string) {
if (index > 0)
return this.substring(0, index) + string + this.substring(index, this.length);
return string + this;
};
console.log('Hello Developers'.customSplice(6,0,'Stack ')) // Hello Stack Developers
console.log('Hello Developers'.replaceString(6,'Stack ')) //// Hello Stack Developers
Jedynym problemem metody podciągowej jest to, że nie będzie działać z indeksem ujemnym. Zawsze pobiera indeks ciągu od 0 pozycji.
function insertString(string, insertion, place) {
return string.replace(string[place] + string[place + 1], string[place] + insertion + string[place + 1])
}
Tak więc dla ciebie byłoby insertString("foo baz", "bar", 3);
Oczywiście byłaby to farba do użycia, ponieważ musisz za każdym razem dostarczać ciąg znaków do funkcji, ale w tej chwili nie wiem, jak zrobić z tego coś łatwiejszego string.replace(insertion, place)
. Pomysł wciąż jednak istnieje.
Możesz używać wyrażeń regularnych z dynamicznym wzorem.
var text = "something";
var output = " ";
var pattern = new RegExp("^\\s{"+text.length+"}");
var output.replace(pattern,text);
wyjścia:
"something "
Zastępuje to text.length
białe znaki na początku łańcucha output
. Te RegExp
środki ^\
- początek linii \s
dowolny biały znak spacji, powtarzające {n}
razy, w tym przypadku text.length
. Służy \\
do \
unikania ukośników odwrotnych podczas budowania tego rodzaju wzorów z ciągów.
innym rozwiązaniem, wytnij sznurek na 2 i umieść sznur między.
var str = jQuery('#selector').text();
var strlength = str.length;
strf = str.substr(0 , strlength - 5);
strb = str.substr(strlength - 5 , 5);
jQuery('#selector').html(strf + 'inserted' + strb);
Możesz to zrobić z regexp w jednym wierszu kodu
const str = 'Hello RegExp!';
const index = 6;
const insert = 'Lovely ';
//'Hello RegExp!'.replace(/^(.{6})(.)/, `$1Lovely $2`);
const res = str.replace(new RegExp(`^(.{${index}})(.)`), `$1${insert}$2`);
console.log(res);
„Hello Lovely RegExp!”
Możesz użyć slice(0,index) + str + slice(index)
. Lub możesz stworzyć dla niego metodę.
String.prototype.insertAt = function(index,str){
return this.slice(0,index) + str + this.slice(index)
}
console.log("foo bar".insertAt(4,'baz ')) //foo baz bar
Możesz split()
główny ciąg i dodać, a następnie użyć normalnegosplice()
String.prototype.splice = function(index,del,...newStrs){
let str = this.split('');
str.splice(index,del,newStrs.join('') || '');
return str.join('');
}
var txt1 = "foo baz"
//inserting single string.
console.log(txt1.splice(4,0,"bar ")); //foo bar baz
//inserting multiple strings
console.log(txt1.splice(4,0,"bar ","bar2 ")); //foo bar bar2 baz
//removing letters
console.log(txt1.splice(1,2)) //f baz
//remving and inseting atm
console.log(txt1.splice(1,2," bar")) //f bar baz
Metoda przyjmuje tablicę tablic, każdy element tablicy reprezentuje pojedynczy splice()
.
String.prototype.splice = function(index,del,...newStrs){
let str = this.split('');
str.splice(index,del,newStrs.join('') || '');
return str.join('');
}
String.prototype.mulSplice = function(arr){
str = this
let dif = 0;
arr.forEach(x => {
x[2] === x[2] || [];
x[1] === x[1] || 0;
str = str.splice(x[0] + dif,x[1],...x[2]);
dif += x[2].join('').length - x[1];
})
return str;
}
let txt = "foo bar baz"
//Replacing the 'foo' and 'bar' with 'something1' ,'another'
console.log(txt.splice(0,3,'something'))
console.log(txt.mulSplice(
[
[0,3,["something1"]],
[4,3,["another"]]
]
))
Chciałem porównać metodę z użyciem podłańcucha i metodę z użyciem wycinka odpowiednio z Base33 i user113716, aby to zrobić, napisałem trochę kodu
zobacz także porównanie wydajności, podciąg, plasterek
Użyty przeze mnie kod tworzy ogromne łańcuchy i wstawia „pasek” łańcucha wiele razy w ogromny łańcuch
if (!String.prototype.splice) {
/**
* {JSDoc}
*
* The splice() method changes the content of a string by removing a range of
* characters and/or adding new characters.
*
* @this {String}
* @param {number} start Index at which to start changing the string.
* @param {number} delCount An integer indicating the number of old chars to remove.
* @param {string} newSubStr The String that is spliced in.
* @return {string} A new string with the spliced substring.
*/
String.prototype.splice = function (start, delCount, newSubStr) {
return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
};
}
String.prototype.splice = function (idx, rem, str) {
return this.slice(0, idx) + str + this.slice(idx + Math.abs(rem));
};
String.prototype.insert = function (index, string) {
if (index > 0)
return this.substring(0, index) + string + this.substring(index, this.length);
return string + this;
};
function createString(size) {
var s = ""
for (var i = 0; i < size; i++) {
s += "Some String "
}
return s
}
function testSubStringPerformance(str, times) {
for (var i = 0; i < times; i++)
str.insert(4, "bar ")
}
function testSpliceStringPerformance(str, times) {
for (var i = 0; i < times; i++)
str.splice(4, 0, "bar ")
}
function doTests(repeatMax, sSizeMax) {
n = 1000
sSize = 1000
for (var i = 1; i <= repeatMax; i++) {
var repeatTimes = n * (10 * i)
for (var j = 1; j <= sSizeMax; j++) {
var actualStringSize = sSize * (10 * j)
var s1 = createString(actualStringSize)
var s2 = createString(actualStringSize)
var start = performance.now()
testSubStringPerformance(s1, repeatTimes)
var end = performance.now()
var subStrPerf = end - start
start = performance.now()
testSpliceStringPerformance(s2, repeatTimes)
end = performance.now()
var splicePerf = end - start
console.log(
"string size =", "Some String ".length * actualStringSize, "\n",
"repeat count = ", repeatTimes, "\n",
"splice performance = ", splicePerf, "\n",
"substring performance = ", subStrPerf, "\n",
"difference = ", splicePerf - subStrPerf // + = splice is faster, - = subStr is faster
)
}
}
}
doTests(1, 100)
Ogólna różnica w wydajności jest w najlepszym razie marginalna i obie metody działają dobrze (nawet na strunach o długości ~ ~ 12000000)
Korzyści z tego podejścia są dwojakie:
const pair = Array.from('USDGBP')
pair.splice(3, 0, '/')
console.log(pair.join(''))