Wstaw ciąg o określonym indeksie


Odpowiedzi:


257

Możesz stworzyć własny splice()ciąg w String.

Polyfill

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

Przykład

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 remjest to wartość bezwzględna.


6
Wiem, że pochodzi z 2010 roku, ale poniższe slicerozwią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.
Eirik Birkeland,

6
@EirikBirkeland: Ciągi są niezmienne. Powyższy kod nie modyfikuje żadnego obiektu. Tak czy inaczej, twoje pojęcie nie modyfikowania „obiektów, których nie znasz ” wykluczałoby metody mutacji Array. Mówisz, że wolisz my_array[my_array.length] = itemzamiast tego my_array.push(item)?

4
Przepraszam, miałem na myśli „przedmioty, których nie posiadasz”. Masz rację splicew tej sprawie; rzeczywiście ciągi są niezmienne. Z tego powodu myślę, że splicejest 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.
Eirik Birkeland,

1
To bardzo zła praktyka zmodyfikować wbudowany obiektów. Jak widzieliśmy w SmooshGate , grozi to zerwaniem kodu, ponieważ nowa funkcjonalność jest dodawana do języka, a jeśli twoja nieodpowiedzialna modyfikacja jakoś dostanie się do biblioteki, która odnotowuje znaczną popularność w Internecie, może zablokować użycie prostej, jasnej nazwy metody dla nowej funkcjonalności.
Sean

401

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

4
@AlejandroSalamancaMazuelo: substringbyłoby dobrze tutaj. sliceOgó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.
Tim Down

8
Czy ES6 oferuje lepszą alternatywę? Przynajmniej można użyć interpolacji ciągów, na przykład`${txt1.slice(0,3)}bar${txt1.slice(3)}`
Jay

1
Nie wykorzystuje to deletefunkcji opisanej powyżej; najlepsza odpowiedź ...
Pan Polywhirl

11
@ Mr.Polywhirl: Nie. W pytaniu nie ma wzmianki o potrzebie zrobienia tego.
Tim Down

133

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)

Odniesienie:


1
Konieczne może być dodanie nawiasów klamrowych {}do bloków if-else.
Mr-IDE

3
Nie, nie muszę. Ale to elsejest zbędne.
Bitterblue,

72

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 !


16

AKTUALIZACJA 2016: Oto kolejna funkcja prototypowa dla zabawy (ale poważniejszej!) Oparta na RegExppodejściu jednowierszowym (z obsługą przedpłaconą undefinedlub 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"

1
Jest to również świetne, jeśli chcesz wstawić tekst o wielu indeksach w ciągu. Zobacz moją odpowiedź poniżej, jeśli tak jest.
Jake Stoeffler,

12

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>!"

1
Próbowałem tej metody, ale zastąpiłem „6” i „11” zmiennymi, które nie działają - co robię źle - pomóżcie proszę. Z góry dziękuję :)
Dex Dave

1
6 i 11 to wskaźniki, przy których tekst zostanie wstawiony do łańcucha. 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>";
Jake Stoeffler,

1
tak, chcę użyć zmiennych całkowitych jako wstawienia, twoja metoda działała - dziękuję - właśnie tego użyłem var a = 6; var b = 11; text = {}; text [a] = "xx"; text [b] = "yy"; - czy jest na to lepszy sposób
Dex Dave

11

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'

9

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.



6

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"

6

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.


Co oznacza absIndex?
Enrique Bermúdez

Btw, dzięki za drugą metodę. To działa jak urok!
Enrique Bermúdez

5
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.


4

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.lengthbiałe znaki na początku łańcucha output. Te RegExpśrodki ^\- początek linii \sdowolny 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.


3

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

3

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!”


2

Za pomocą plasterka

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

Metoda łączenia ciągów

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

Stosowanie splice () przy wielu indeksach

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"]]
]

))


1

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)


0
  1. Utwórz instancję tablicy z ciągu
  2. Użyj Array # splice
  3. Ponownie ustaw Stringify używając Array # join

Korzyści z tego podejścia są dwojakie:

  1. Prosty
  2. Zgodny z kodem Unicode

const pair = Array.from('USDGBP')
pair.splice(3, 0, '/')
console.log(pair.join(''))

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.