Come posso sostituire un carattere in un determinato indice in JavaScript?


544

Ho una stringa, diciamo Hello worlde devo sostituire il carattere all'indice 3. Come posso sostituire un carattere specificando un indice?

var str = "hello world";

Ho bisogno di qualcosa del genere

str.replaceAt(0,"h");

131
La cosa strana è che str[0] = 'x'non sembra lanciare errori, ma non ha l'effetto desiderato!
Michael,

6
@Michael con quello otterresti l'indice a 0, impostalo su 'x', quell'istruzione su se stessa restituirebbe il nuovo valore; 'X'. ma tutto ciò non cambia l'originale, quindi è perfettamente valido, proprio non quello che ti aspettavi. non è un riferimento
Paul Scheltema,

8
@Michael lo fa se "use strict"è attivato: Uncaught TypeError: Cannot assign to read only property '0' of string 'hello world'(almeno nei browser
webkit

1
Le stringhe Javascript sono immutabili, non possono essere modificate "sul posto", quindi non puoi modificare un singolo carattere. infatti ogni ricorrenza della stessa stringa è UN oggetto.
Martijn Scheffer

ok, vedi la risposta: D
Martijn Scheffer

Risposte:


611

In JavaScript, le stringhe sono immutabili , il che significa che il meglio che puoi fare è creare una nuova stringa con il contenuto modificato e assegnare la variabile in modo che punti ad essa.

Dovrai definire replaceAt()tu stesso la funzione:

String.prototype.replaceAt = function(index, replacement) {
    return this.substr(0, index) + replacement + this.substr(index + replacement.length);
}

E usalo in questo modo:

var hello = "Hello World";
alert(hello.replaceAt(2, "!!")); // Should display He!!o World

101
Si noti che in genere non è una buona idea estendere le classi JavaScript di base. Utilizzare invece una semplice funzione di utilità.
Ates Goral,

86
Devo chiedere perché? Il supporto del prototipo è lì per questo scopo.
Cem Kalyoncu,

30
@CemKalyoncu: può far funzionare male il codice con altre librerie. Ma non sono mai stato morso da quello me stesso.
alex

6
@alex: hai ragione, devi davvero controllare se quella funzione esiste prima di farlo. Ma anche se lo fa, dovrebbe fare esattamente la stessa operazione.
Cem Kalyoncu,

80
Non sono d'accordo, anche se si rileva se la funzione esiste, una libreria successiva può comunque utilizzare / creare una funzione simile - 2 idee cattive che ne peggiorano una. In generale, non scherzare mai con il codice di altre persone (incluso il sistema principale). Crea una nuova funzione.
martyman,

93

Non esiste alcuna replaceAtfunzione in JavaScript. È possibile utilizzare il seguente codice per sostituire qualsiasi carattere in qualsiasi stringa nella posizione specificata:

function rep() {
    var str = 'Hello World';
    str = setCharAt(str,4,'a');
    alert(str);
}

function setCharAt(str,index,chr) {
    if(index > str.length-1) return str;
    return str.substr(0,index) + chr + str.substr(index+1);
}
<button onclick="rep();">click</button>



Preferisco questa soluzione perché è possibile sostituire un singolo carattere con esso. La soluzione che ha il maggior numero di voti non funziona se si desidera sostituire solo un carattere. Funziona solo quando si sostituiscono due personaggi! Inoltre, substr dovrebbe essere sostituito con sottostringa come menzionato in molti altri commenti.
Gignu,

74

Non puoi. Prendi i caratteri prima e dopo la posizione e concateli in una nuova stringa:

var s = "Hello world";
var index = 3;
s = s.substring(0, index) + 'x' + s.substring(index + 1);

In realtà sì, puoi, ma sarebbe eccessivo. È possibile impostare un'espressione regolare per saltare il primo indice: 1 carattere e abbinare il carattere nell'indice. È possibile utilizzare String.replace con quell'espressione regolare per effettuare una sostituzione diretta e diretta. Ma è eccessivo. Quindi, in pratica non puoi. Ma in teoria puoi.
Ates Goral,

12
@Ates: la funzione di sostituzione non esegue una sostituzione sul posto, crea una nuova stringa e la restituisce.
Guffa,

2
MDN suggerisce di utilizzare String.prototype.substringoltre String.prototype.substr.
Mikemike,

33

Ci sono molte risposte qui e tutte sono basate su due metodi:

  • METODO 1: dividere la stringa usando due sottostringhe e riempire il carattere tra loro
  • METODO2: converti la stringa in array di caratteri, sostituisci un membro dell'array e unisciti a esso

Personalmente, userei questi due metodi in diversi casi. Lasciatemi spiegare.

@FabioPhms: il tuo metodo era quello inizialmente usato e temevo che fosse un problema con la stringa con molti caratteri. Tuttavia, la domanda è: quanti personaggi ci sono? L'ho testato su 10 paragrafi "Lorem ipsum" e ci sono voluti alcuni millisecondi. Poi l'ho provato su una stringa 10 volte più grande - non c'era davvero nessuna grande differenza. Hm.

@vsync, @Cory Mawhorter: i tuoi commenti non sono ambigui; tuttavia, di nuovo, cos'è una stringa di grandi dimensioni? Concordo sul fatto che per 32 ... 100kb le prestazioni dovrebbero essere migliori e si dovrebbe usare la variante di sottostringa per questa operazione di sostituzione dei caratteri.

Ma cosa succederà se dovrò effettuare parecchie sostituzioni?

Avevo bisogno di eseguire i miei test per dimostrare cosa è più veloce in quel caso. Diciamo che abbiamo un algoritmo che manipolerà una stringa relativamente corta composta da 1000 caratteri. Ci aspettiamo che in media ogni carattere in quella stringa venga sostituito ~ 100 volte. Quindi, il codice per testare qualcosa del genere è:

var str = "... {A LARGE STRING HERE} ...";

for(var i=0; i<100000; i++)
{
  var n = '' + Math.floor(Math.random() * 10);
  var p = Math.floor(Math.random() * 1000);
  // replace character *n* on position *p*
}

Ho creato un violino per questo, ed è qui . Esistono due test, TEST1 (sottostringa) e TEST2 (conversione array).

risultati:

  • TEST1: 195ms
  • TEST2: 6ms

Sembra che la conversione dell'array superi la sottostringa di 2 ordini di grandezza! Quindi - che diavolo è successo qui ???

Ciò che effettivamente accade è che tutte le operazioni in TEST2 vengono eseguite sull'array stesso, usando espressioni di assegnazione simili strarr2[p] = n. L'assegnazione è molto rapida rispetto alla sottostringa su una stringa di grandi dimensioni ed è evidente che vincerà.

Quindi, si tratta solo di scegliere lo strumento giusto per il lavoro. Ancora.


7
Spostato il tuo test su jsperf, con risultati molto diversi: jsperf.com/string-replace-character . Si tratta solo di scegliere lo strumento giusto per il lavoro;)
colllin,

1
@colllin: sono assolutamente d'accordo. Quindi ho quasi clonato letteralmente i test da jsfiddle a jsperf. Tuttavia, oltre a utilizzare lo strumento giusto, devi farlo nel modo giusto. Presta attenzione al problema, stiamo parlando di cosa accadrà se dovremo apportare alcune sostituzioni in un algoritmo. L'esempio concreto include 10000 sostituzioni. Ciò significa che un test dovrebbe includere 10000 sostituzioni. Quindi, usando jsperf, ho ottenuto risultati abbastanza coerenti, vedi: jsperf.com/… .
OzrenTkalcecKrznaric,

1
ecco perché non mi piace JavaScript. non sono previsti casi d'uso così frequenti, intuitivi, ovvi. Penseresti agli scrittori di javascript che le persone potrebbero voler sostituire i caratteri all'interno delle stringhe e che avrebbero deciso di mettere metodi di praticità nella lingua.
ahnbizcad,

1
@colllin ha fatto qualcosa di diverso da OzrenTkalcecKrznaric. OzrenTkalcecKrznaric ha ipotizzato che la stringa sia statica e che la divisione possa essere ottimizzata prima delle esecuzioni. Il che non è necessariamente vero. se devi dividere ad ogni corsa, l'approccio di sottostringa è circa due volte più veloce su stringhe piccole, e solo più veloce quanto più grande diventa la stringa. A mio avviso ciò rende la sottostringa la migliore implementazione per la maggior parte dei casi d'uso, escludendo un gran numero di modifiche su una grande stringa statica.
WiR3D

3
Il problema è che su test2 la divisione e l'unione sono al di fuori del ciclo for, dove si confronta la sostituzione del singolo carattere con una multipla (ingiusta), il primo metodo è più veloce per le sostituzioni singole e il secondo è migliore per le sostituzioni concatenate una dopo l'altra
Θεόφιλος Μουρατίδης il

32

Il lavoro con i vettori è generalmente più efficace per contattare String.

Suggerisco la seguente funzione:

String.prototype.replaceAt=function(index, char) {
    var a = this.split("");
    a[index] = char;
    return a.join("");
}

Esegui questo frammento:

String.prototype.replaceAt=function(index, char) {
    var a = this.split("");
    a[index] = char;
    return a.join("");
}

var str = "hello world";
str = str.replaceAt(3, "#");

document.write(str);


9
questo è male per stringhe di grandi dimensioni, non è necessario creare un array con una quantità folle di celle se puoi semplicemente usare substr per tagliarlo ...
vsync

1
Utile se devi cambiare molti personaggi ed è semplice.
Sheepy,

6
Ho creato un test su jsperf: jsperf.com/replace-character-by-index - Substr è molto più veloce e coerente da 32 byte a 100kb. Ho valutato questo e per quanto mi faccia male dire, anche se sembra più bello, substr è la scelta migliore per stringhe di qualsiasi dimensione.
Cory Mawhorter,

Questo è abbastanza non ottimale.
Radko Dinev,

Questa è una buona soluzione rapida se sai che stai per usare stringhe di piccole dimensioni. Se stai bene con l'estensione dei prototipi, potresti ottenere un comportamento simile in 2 righe:Array.prototype.replace = function(index, val) { this[index] = val; return this; }; 'word'.split('').replace(1, '0').join(''); // returns 'w0rd'
Michael Plautz,

29

Nelle stringhe Javascript sono immutabili, quindi devi fare qualcosa del genere

var x = "Hello world"
x = x.substring(0, i) + 'h' + x.substring(i+1);

Per sostituire il carattere in x at i con 'h'


28
str = str.split('');
str[3] = 'h';
str = str.join('');

4
Chiaro e semplice, ma attualmente non funziona con le emoji (come 😀) quando si utilizza splitejoin
Verde

1
Con es6 penso che Array.from (str) potrebbe essere un'opzione migliore ora, ma sono venuto qui con quella conoscenza e ho imparato qualcosa altrettanto conciso da te, quindi grazie!
David Kamer,

7

One-liner usando String.replace con callback (nessun supporto emoji):

// 0 - index to replace, 'f' - replacement string
'dog'.replace(/./g, (c, i) => i == 0? 'f': c)
// "fog"

Ha spiegato:

//String.replace will call the callback on each pattern match
//in this case - each character
'dog'.replace(/./g, function (character, index) {
   if (index == 0) //we want to replace the first character
     return 'f'
   return character //leaving other characters the same
})

6

Questo metodo è utile per stringhe di lunghezza ridotta, ma può essere lento per testo più grande.

var x = "White Dog";
var arr = x.split(""); // ["W", "h", "i", "t", "e", " ", "D", "o", "g"]
arr.splice(6, 1, 'F');
var result = arr.join(""); // "White Fog"

/* 
  Here 6 is starting index and 1 is no. of array elements to remove and 
  final argument 'F' is the new character to be inserted. 
*/

3

@CemKalyoncu: Grazie per l'ottima risposta!

L'ho anche adattato leggermente per renderlo più simile al metodo Array.splice (e ho preso in considerazione la nota di @Ates):

spliceString=function(string, index, numToDelete, char) {
      return string.substr(0, index) + char + string.substr(index+numToDelete);
   }

var myString="hello world!";
spliceString(myString,myString.lastIndexOf('l'),2,'mhole'); // "hello wormhole!"

Non sono sicuro del perché sia ​​stato votato verso il basso. È una risposta legittima. Funziona come indicato. Ed è coerente con la Array.splicefunzionalità di tipo.
Scrimothy,

3

Funziona in modo simile a Array.splice:

String.prototype.splice = function (i, j, str) {
    return this.substr(0, i) + str + this.substr(j, this.length);
};

3

Potresti provare

var strArr = str.split("");

strArr[0] = 'h';

str = strArr.join("");

2

Se si desidera sostituire i caratteri nella stringa, è necessario creare stringhe mutabili. Questi sono essenzialmente array di caratteri. Potresti creare una fabbrica:

  function MutableString(str) {
    var result = str.split("");
    result.toString = function() {
      return this.join("");
    }
    return result;
  }

Quindi è possibile accedere ai caratteri e l'intero array viene convertito in stringa se utilizzato come stringa:

  var x = MutableString("Hello");
  x[0] = "B"; // yes, we can alter the character
  x.push("!"); // good performance: no new string is created
  var y = "Hi, "+x; // converted to string: "Hi, Bello!"

2

Generalizzando la risposta di Afanasii Kurakin, abbiamo:

function replaceAt(str, index, ch) {
    return str.replace(/./g, (c, i) => i == index ? ch : c)
}

let str = 'Hello World'
str = replaceAt(str, 1, 'u')
console.log(str) // Hullo World

Espandiamo e spieghiamo sia l'espressione regolare che la funzione di sostituzione:

function replaceAt(str, index, newChar) {
    function replacer(origChar, strIndex) {
        if (strIndex === index)
            return newChar
        else
            return origChar
    }
    return str.replace(/./g, replacer)
}

let str = 'Hello World'
str = replaceAt(str, 1, 'u')
console.log(str) // Hullo World

L'espressione regolare .corrisponde esattamente a un carattere. Lo gfa abbinare ogni personaggio in un ciclo for. La replacerfunzione viene chiamata in base al carattere originale e all'indice di dove si trova quel carattere nella stringa. Facciamo una semplice ifdichiarazione per determinare se restituiremo origCharo newChar.


2

È possibile estendere il tipo di stringa per includere il metodo inset:

String.prototype.append = function (index,value) {
  return this.slice(0,index) + value + this.slice(index);
};

var s = "New string";
alert(s.append(4,"complete "));

Quindi puoi chiamare la funzione:


1

Ho fatto una funzione che fa qualcosa di simile a quello che chiedi, controlla se un carattere nella stringa è in una matrice di caratteri non consentiti se lo sostituisce con ''

    var validate = function(value){
        var notAllowed = [";","_",">","<","'","%","$","&","/","|",":","=","*"];
        for(var i=0; i<value.length; i++){
            if(notAllowed.indexOf(value.charAt(i)) > -1){
               value = value.replace(value.charAt(i), "");
               value = validate(value);
            }
       }
      return value;
   }

1

questo è facilmente raggiungibile con RegExp!

const str = 'Hello RegEx!';
const index = 11;
const replaceWith = 'p';

//'Hello RegEx!'.replace(/^(.{11})(.)/, `$1p`);
str.replace(new RegExp(`^(.{${ index }})(.)`), `$1${ replaceWith }`);

//< "Hello RegExp"

1

Ecco una versione che mi è venuta in mente se vuoi dare uno stile a parole o singoli caratteri nel loro indice in reagire / javascript.

replaceAt( yourArrayOfIndexes, yourString/orArrayOfStrings ) 

Esempio di lavoro: https://codesandbox.io/s/ov7zxp9mjq

function replaceAt(indexArray, [...string]) {
    const replaceValue = i => string[i] = <b>{string[i]}</b>;
    indexArray.forEach(replaceValue);
    return string;
}

Ed ecco un altro metodo alternativo

function replaceAt(indexArray, [...string]) {
    const startTag = '<b>';
    const endTag = '</b>';
    const tagLetter = i => string.splice(i, 1, startTag + string[i] + endTag);
    indexArray.forEach(tagLetter);
    return string.join('');
}

E un altro...

function replaceAt(indexArray, [...string]) {
    for (let i = 0; i < indexArray.length; i++) {
        string = Object.assign(string, {
          [indexArray[i]]: <b>{string[indexArray[i]]}</b>
        });
    }
    return string;
}

0

So che questo è vecchio ma la soluzione non funziona per l'indice negativo, quindi aggiungo una patch. spero che aiuti qualcuno

String.prototype.replaceAt=function(index, character) {
    if(index>-1) return this.substr(0, index) + character + this.substr(index+character.length);
    else return this.substr(0, this.length+index) + character + this.substr(index+character.length);

}

0

Diciamo che vuoi sostituire l' Kthindice (indice basato su 0) con 'Z'. Potresti usare Regexper fare questo.

var re = var re = new RegExp("((.){" + K + "})((.){1})")
str.replace(re, "$1A$`");

Qualche idea sul perché questo tag non sia utile?
ksp

Non ho verificato se questa regex funziona, ma forse è sottoposta a downgrade perché probabilmente è molto più veloce creare una nuova stringa, piuttosto che compilare una macchina a stati (espressione regolare), che è molto costosa.
Felo Vilches,

0

È possibile utilizzare la seguente funzione per sostituire Charactero Stringin una posizione particolare di una stringa. Per sostituire tutti i seguenti casi di corrispondenza utilizzare la String.prototype.replaceAllMatches()funzione.

String.prototype.replaceMatch = function(matchkey, replaceStr, matchIndex) {
    var retStr = this, repeatedIndex = 0;
    for (var x = 0; (matchkey != null) && (retStr.indexOf(matchkey) > -1); x++) {
        if (repeatedIndex == 0 && x == 0) {
            repeatedIndex = retStr.indexOf(matchkey);
        } else { // matchIndex > 0
            repeatedIndex = retStr.indexOf(matchkey, repeatedIndex + 1);
        }
        if (x == matchIndex) {
            retStr = retStr.substring(0, repeatedIndex) + replaceStr + retStr.substring(repeatedIndex + (matchkey.length));
            matchkey = null; // To break the loop.
        }
    }
    return retStr;
};

Test:

var str = "yash yas $dfdas.**";

console.log('Index Matched replace : ', str.replaceMatch('as', '*', 2) );
console.log('Index Matched replace : ', str.replaceMatch('y', '~', 1) );

Produzione:

Index Matched replace :  yash yas $dfd*.**
Index Matched replace :  yash ~as $dfdas.**

-1

Ecco la mia soluzione usando l'operatore ternario e cartografico. Più leggibile, più facilmente gestibile e più facile da capire se me lo chiedi.

È più in es6 e migliori pratiche.

function replaceAt() {
  const replaceAt = document.getElementById('replaceAt').value;

  const str = 'ThisIsATestStringToReplaceCharAtSomePosition';
  const newStr = Array.from(str).map((character, charIndex) => charIndex === (replaceAt - 1) ? '' : character).join('');

  console.log(`New string: ${newStr}`);
}
<input type="number" id="replaceAt" min="1" max="44" oninput="replaceAt()"/>


-3

I metodi qui sono complicati. Lo farei così:

var myString = "this is my string";
myString = myString.replace(myString.charAt(number goes here), "insert replacement here");

Questo è semplice come si arriva.


6
Non attualmente. In effetti sostituirà la prima occorrenza del personaggio. Ancora sbagliato.
Tomáš Zato - Ripristina Monica il
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.