Inserisci una stringa in un indice specifico


Risposte:


257

Potresti prototipare il tuo splice()in 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));
    };
}

Esempio

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"


EDIT: modificato per garantire che remsia un valore assoluto.


6
So che è del 2010, ma la slicesoluzione di seguito è migliore e più semplice. (La giuntura è distruttiva, la fetta no, ed è meglio evitare di modificare "oggetti che non conosci"). Questa soluzione non dovrebbe assolutamente essere la prima risposta visibile, anche se potrebbe aver avuto senso in quel momento.
Eirik Birkeland,

6
@EirikBirkeland: le stringhe sono immutabili. Il codice sopra non modifica alcun oggetto. In ogni caso, la tua idea di non modificare "oggetti che non conosci " precluderebbe i metodi di mutazione dell'array. Stai dicendo che preferiresti fare my_array[my_array.length] = iteminvece di my_array.push(item)?

4
Scusa, intendevo "oggetti che NON PROPRI". Hai ragione splicein questo caso; infatti le stringhe sono immutabili. Per questo motivo penso che splicesia una cattiva scelta di parole chiave. La mia obiezione principale è contro l'estensione dei prototipi arbitrariamente, a meno che non siano polifillamenti standard.
Eirik Birkeland,

1
È una cattiva pratica modificare un oggetto incorporato. Come abbiamo visto con SmooshGate , questo rischia di violare il codice man mano che nuove funzionalità vengono aggiunte al linguaggio e, se la tua modifica irresponsabile dovesse in qualche modo entrare in una libreria che vede un assorbimento significativo attraverso il Web, potrebbe bloccare l'uso di un nome di metodo semplice e chiaro per nuove funzionalità.
Sean

401

L'inserimento in un indice specifico (piuttosto che, per esempio, nel primo carattere di spazio) deve usare lo slicing / sottostringa di stringhe:

var txt2 = txt1.slice(0, 3) + "bar" + txt1.slice(3);

4
@AlejandroSalamancaMazuelo: substringstarebbe bene qui. Preferisco slicein generale perché è più flessibile (indici negativi, ad es "foo baz".slice(1, -2).). È anche leggermente più corto, per quel poco che vale.
Tim Down

8
ES6 offre un'alternativa migliore? Potrebbe almeno usare l'interpolazione di stringhe, come`${txt1.slice(0,3)}bar${txt1.slice(3)}`
Jay,

1
Questo non utilizza la deletefunzionalità inclusa in quanto sopra; risposta migliore ...
Mr. Polywhirl,

11
@ Mr.Polywhirl: No. La domanda non fa menzione della necessità di farlo.
Tim Down,

133

Ecco un metodo che ho scritto che si comporta come tutti gli altri linguaggi di programmazione:

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)

Riferimento:


1
Potrebbe essere necessario aggiungere parentesi graffe {}ai blocchi if-else.
Mr IDE,

3
No, non è necessario. Ma elseè ridondante.
Bitterblue,

72

Basta fare la seguente funzione:

function insert(str, index, value) {
    return str.substr(0, index) + value + str.substr(index);
}

e poi usalo così:

alert(insert("foo baz", 4, "bar "));

Uscita: foo bar baz

Si comporta esattamente come C. (Sharp) String.Insert (int startIndex, valore stringa).

NOTA: questa funzione di inserimento inserisce il valore di stringa (terzo parametro) prima dell'indice intero specificato (secondo parametro) nella stringa str (primo parametro), quindi restituisce la nuova stringa senza modificare str !


16

AGGIORNAMENTO 2016: Ecco un'altra funzione prototipo just-for-fun (ma più seria!) Basata sull'approccio one-liner RegExp(con supporto anteprime attivo undefinedo negativo 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"

Soluzione just-for-fun precedente (fino al 2012) :

var index = 4,
    what  = 'bar ';

'foo baz'.replace(/./g, function(v, i) {
    return i === index - 1 ? v + what : v;
});  // "foo bar baz"

1
Ciò è ottimo anche se è necessario inserire testo in più indici in una stringa. Vedi la mia risposta qui sotto in questo caso.
Jake Stoeffler,

12

Se qualcuno è alla ricerca di un modo per inserire testo in più indici in una stringa, prova questo:

String.prototype.insertTextAtIndices = function(text) {
    return this.replace(/./g, function(character, index) {
        return text[index] ? text[index] + character : character;
    });
};

Ad esempio, puoi usarlo per inserire <span>tag in determinati offset in una stringa:

var text = {
    6: "<span>",
    11: "</span>"
};

"Hello world!".insertTextAtIndices(text); // returns "Hello <span>world</span>!"

1
Ho provato questo metodo ma ho sostituito '6' e '11' con variabili che non funzionano - cosa sto facendo di sbagliato - aiuto per favore. Grazie in anticipo :)
Dex Dave,

1
6 e 11 sono gli indici in cui il testo verrà inserito nella stringa. 6: "<span>"dice: all'indice 6, inserire il testo "<span>". Stai dicendo che vuoi usare il valore di una variabile intera come indice di inserimento? In tal caso, prova qualcosa del generevar a=6, text = {}; text[a] = "<span>";
Jake Stoeffler,

1
sì, voglio usare variabili intere come inserimento, il tuo metodo ha funzionato - grazie - questo è quello che ho usato var a = 6; var b = 11; text = {}; text [a] = "xx"; text [b] = "yy"; - c'è un modo migliore per scriverlo però
Dex Dave,

11

Questo sta fondamentalmente facendo quello che @ Bass33 sta facendo tranne che sto dando anche la possibilità di usare un indice negativo per contare dalla fine. Un po 'come il metodo substr consente.

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

Caso d'uso: diciamo che hai immagini a grandezza naturale usando una convenzione di denominazione ma non puoi aggiornare i dati per fornire anche URL di anteprima.

var url = '/images/myimage.jpg';
var thumb = url.insert(-4, '_thm');

//    result:  '/images/myimage_thm.jpg'

9

Dato il tuo esempio attuale, potresti ottenere il risultato con entrambi

var txt2 = txt1.split(' ').join(' bar ')

o

var txt2 = txt1.replace(' ', ' bar ');

ma dato che puoi fare simili ipotesi, puoi anche saltare direttamente all'esempio di Gullen.

In una situazione in cui non puoi davvero fare ipotesi diverse da quelle basate sull'indice di caratteri, allora sceglierei una soluzione di sottostringa.



6

So che questo è un vecchio thread, tuttavia, ecco un approccio davvero efficace.

var tn = document.createTextNode("I am just  to help")
t.insertData(10, "trying");

La cosa fantastica di questo è che costringe il contenuto del nodo. Quindi, se questo nodo fosse già presente sul DOM, non sarebbe necessario utilizzare alcun selettore di query o aggiornare innerText. Le modifiche si rifletterebbero a causa della sua associazione.

Se avessi bisogno di una stringa, accedi semplicemente alla proprietà del contenuto del testo del nodo.

tn.textContent
#=> "I am just trying to help"

6

Bene, possiamo usare sia la sottostringa che il metodo 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

L'unico problema di un metodo di sottostringa è che non funzionerà con un indice negativo. Prende sempre l'indice di stringa dalla 0a posizione.


Cosa significa absIndex?
Enrique Bermúdez,

A proposito, grazie per il secondo metodo. Esso funziona magicamente!
Enrique Bermúdez,

5
function insertString(string, insertion, place) {
  return string.replace(string[place] + string[place + 1], string[place] + insertion + string[place + 1])
}

Quindi, per te, sarebbe insertString("foo baz", "bar", 3);

Ovviamente, questa sarebbe una vernice da usare perché devi fornire la tua stringa alla funzione ogni volta, ma al momento non so come renderla più facile come una string.replace(insertion, place). L'idea è ancora valida.


4

È possibile utilizzare le espressioni regolari con un modello dinamico .

var text = "something";
var output = "                    ";
var pattern = new RegExp("^\\s{"+text.length+"}");
var output.replace(pattern,text);

uscite:

"something      "

Questo sostituisce i text.lengthcaratteri di spazi bianchi all'inizio della stringa output. I RegExpmezzi ^\- inizio di una riga \squalsiasi carattere di spazio bianco, {n}tempi ripetuti , in questo caso text.length. Usare \\per \sfuggire alle barre rovesciate quando si costruisce questo tipo di schemi dalle stringhe.


3

un'altra soluzione, tagliare la stringa in 2 e mettere una stringa in mezzo.

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

Puoi farlo facilmente con regexp in una riga di codice

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

"Ciao Lovely RegExp!"


2

Usando la fetta

È possibile utilizzare slice(0,index) + str + slice(index). Oppure puoi creare un metodo per questo.

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

Metodo di giunzione per stringhe

È possibile split()aggiungere la stringa principale e quindi utilizzare normalesplice()

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

Applicazione di splice () su più indici

Il metodo accetta una matrice di matrici ogni elemento della matrice che rappresenta un singolo 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

Volevo confrontare il metodo usando la sottostringa e il metodo usando rispettivamente slice da Base33 e user113716, per fare ciò ho scritto del codice

anche dare un'occhiata a questo confronto delle prestazioni, sottostringa, fetta

Il codice che ho usato crea stringhe enormi e inserisce la stringa "bar" più volte nella stringa enorme

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)

La differenza generale nelle prestazioni è nella migliore delle ipotesi marginale ed entrambi i metodi funzionano bene (anche su stringhe di lunghezza ~~ 12000000)


0
  1. Crea un'istanza di una matrice dalla stringa
  2. Usa la matrice # giunzione
  3. Stringify di nuovo usando Array # join

I vantaggi di questo approccio sono duplici:

  1. Semplice
  2. Conforme al punto di codice Unicode

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.