Bagaimana cara mengganti karakter pada indeks tertentu dalam JavaScript?


544

Saya memiliki string, katakanlah Hello worlddan saya perlu mengganti char di indeks 3. Bagaimana saya bisa mengganti char dengan menentukan indeks?

var str = "hello world";

Saya butuh sesuatu seperti

str.replaceAt(0,"h");

131
Yang aneh adalah itu str[0] = 'x'sepertinya tidak menimbulkan kesalahan, namun tidak memiliki efek yang diinginkan!
Michael

6
@Michael dengan itu Anda akan mendapatkan indeks pada 0, atur ke 'x', pernyataan itu sendiri akan mengembalikan nilai baru; 'x'. tetapi semua itu tidak mengubah yang asli, jadi itu benar-benar valid, tidak seperti yang Anda harapkan. ini bukan referensi
Paul Scheltema

8
@Michael tidak jika "use strict"diaktifkan: Uncaught TypeError: Cannot assign to read only property '0' of string 'hello world'(setidaknya di browser webkit)
Jan Turoň

1
String Javascript tidak dapat diubah, mereka tidak dapat dimodifikasi "di tempat" sehingga Anda tidak dapat mengubah satu karakter. sebenarnya setiap kemunculan string yang sama adalah SATU objek.
Martijn Scheffer

ok, lihat jawabannya: D
Martijn Scheffer

Jawaban:


611

Dalam JavaScript, string tidak dapat diubah , yang berarti yang terbaik yang dapat Anda lakukan adalah membuat string baru dengan konten yang diubah dan menetapkan variabel untuk mengarahkannya.

Anda harus menentukan replaceAt()sendiri fungsinya:

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

Dan gunakan seperti ini:

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

101
Perhatikan bahwa umumnya bukan ide yang bagus untuk memperpanjang kelas JavaScript dasar. Gunakan fungsi utilitas biasa saja.
Ates Goral

86
Saya harus bertanya mengapa? Dukungan prototipe ada untuk tujuan ini.
Cem Kalyoncu

30
@CemKalyoncu: Ini dapat membuat kode bermain buruk dengan perpustakaan lain. Tapi saya sendiri belum pernah digigit olehnya.
alex

6
@alex: Anda benar tentang itu, Anda benar-benar perlu memeriksa apakah fungsi itu ada sebelum melakukannya. Tetapi bahkan jika itu terjadi, itu harus melakukan operasi yang persis sama.
Cem Kalyoncu

80
Saya tidak setuju, bahkan jika Anda mendeteksi apakah ada fungsi perpustakaan nanti masih dapat menggunakan / membuat fungsi yang sama - 2 ide buruk membuat yang lebih buruk. Secara umum, tidak pernah bermain-main dengan kode orang lain (termasuk sistem inti). Buat fungsi baru.
martyman

93

Tidak ada replaceAtfungsi di JavaScript. Anda dapat menggunakan kode berikut untuk mengganti karakter dalam string apa pun pada posisi yang ditentukan:

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>



Saya lebih suka solusi ini karena Anda dapat mengganti satu karakter dengannya. Solusi yang paling banyak mendapat upvotes tidak berfungsi jika Anda hanya ingin mengganti satu karakter. Ini hanya berfungsi ketika mengganti dua karakter! Substring juga harus diganti dengan substring seperti yang disebutkan dalam banyak komentar lainnya.
gignu

74

Kamu tidak bisa Ambil karakter sebelum dan sesudah posisi dan masukkan ke string baru:

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

Sebenarnya, ya, Anda bisa, tetapi itu akan menjadi kerja keras. Anda bisa mengatur ekspresi reguler untuk melewati indeks pertama - 1 karakter dan mencocokkan karakter di indeks. Anda dapat menggunakan String.replace dengan ekspresi reguler untuk melakukan penggantian langsung di tempat. Tapi itu berlebihan. Jadi, dalam praktiknya Anda tidak bisa. Namun secara teori, Anda bisa.
Ates Goral

12
@Ates: Fungsi penggantian tidak melakukan penggantian di tempat, itu membuat string baru dan mengembalikannya.
Guffa

2
MDN menyarankan untuk menggunakan String.prototype.substringlebih String.prototype.substr.
Mikemike

33

Ada banyak jawaban di sini, dan semuanya didasarkan pada dua metode:

  • METODE1: pisahkan string menggunakan dua substring dan isi karakter di antara mereka
  • METHOD2: konversikan string ke karakter array, ganti satu anggota array dan bergabunglah

Secara pribadi, saya akan menggunakan dua metode ini dalam kasus yang berbeda. Biarkan saya jelaskan.

@FabioPhms: Metode Anda adalah yang awalnya saya gunakan dan saya takut itu buruk pada string dengan banyak karakter. Namun, pertanyaannya adalah apa yang banyak karakter? Saya mengujinya pada 10 paragraf "lorem ipsum" dan butuh beberapa milidetik. Lalu saya mengujinya pada string 10 kali lebih besar - benar-benar tidak ada perbedaan besar. Hm

@vsync, @Cory Mawhorter: Komentar Anda tidak ambigu; Namun, sekali lagi, apa itu string besar? Saya setuju bahwa untuk 32 ... kinerja 100kb harus lebih baik dan kita harus menggunakan substring-varian untuk operasi penggantian karakter yang satu ini.

Tetapi apa yang akan terjadi jika saya harus membuat beberapa penggantian?

Saya perlu melakukan tes sendiri untuk membuktikan apa yang lebih cepat dalam kasus itu. Katakanlah kita memiliki algoritma yang akan memanipulasi string yang relatif pendek yang terdiri dari 1000 karakter. Kami berharap bahwa rata-rata setiap karakter dalam string itu akan diganti ~ 100 kali. Jadi, kode untuk menguji sesuatu seperti ini adalah:

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*
}

Saya membuat biola untuk ini, dan itu ada di sini . Ada dua tes, TEST1 (substring) dan TEST2 (konversi array).

Hasil:

  • UJI1: 195ms
  • TEST2: 6ms

Tampaknya konversi array mengalahkan substring dengan 2 kali lipat! Jadi - apa yang terjadi di sini ???

Apa yang sebenarnya terjadi adalah bahwa semua operasi di TEST2 dilakukan pada array itu sendiri, menggunakan ekspresi penugasan seperti strarr2[p] = n. Penugasan benar-benar cepat dibandingkan dengan substring pada string besar, dan jelas bahwa itu akan menang.

Jadi, ini semua tentang memilih alat yang tepat untuk pekerjaan itu. Lagi.


7
Pindah tes Anda ke jsperf, dengan hasil yang sangat berbeda: jsperf.com/string-replace-character . Ini semua tentang memilih alat yang tepat untuk pekerjaan;)
colllin

1
@ Colllin: Saya sangat setuju. Jadi saya hampir mengkloning tes dari jsfiddle ke jsperf. Namun, selain menggunakan alat yang tepat, Anda harus melakukannya dengan cara yang benar. Perhatikan masalah, kita berbicara tentang apa yang akan terjadi jika kita harus membuat beberapa penggantian dalam suatu algoritma. Contoh konkret meliputi 10.000 penggantian. Ini berarti satu tes harus mencakup 10.000 penggantian. Jadi, menggunakan jsperf, saya mendapat hasil yang cukup konsisten, lihat: jsperf.com/… .
OzrenTkalcecKrznaric

1
ini sebabnya saya tidak suka javascript. case penggunaan yang sering, intuitif, jelas tidak disediakan. Anda akan berpikir itu akan terjadi pada penulis javascript bahwa orang mungkin ingin mengganti karakter dalam string, dan bahwa mereka akan memutuskan untuk memasukkan metode kenyamanan ke dalam bahasa.
ahnbizcad

1
@colllin melakukan sesuatu yang berbeda dengan OzrenTkalcecKrznaric. OzrenTkalcecKrznaric membuat asumsi bahwa string statis dan pemisahan dapat dioptimalkan sebelum berjalan. Yang belum tentu benar. jika Anda harus membagi pada setiap menjalankan maka pendekatan substring sekitar dua kali lebih cepat 4x pada string kecil, dan hanya lebih cepat semakin besar string yang didapat. Menurut pendapat saya ini membuat substring implementasi yang lebih baik untuk sebagian besar kasus penggunaan, kecuali sejumlah besar perubahan pada string statis besar.
WiR3D

3
Masalahnya adalah bahwa pada test2 split dan join berada di luar loop for, di mana Anda membandingkan penggantian char tunggal dengan multiple (tidak adil), metode pertama lebih cepat untuk penggantian tunggal dan yang kedua lebih baik untuk penggantian dirantai satu demi satu
Θεόφιλος Μουρατίδης

32

Bekerja dengan vektor biasanya paling efektif untuk menghubungi String.

Saya menyarankan fungsi berikut:

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

Jalankan cuplikan ini:

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
ini buruk untuk string besar, tidak perlu membuat Array dengan jumlah sel gila jika Anda bisa menggunakan substr untuk memotongnya ...
vsync

1
Berguna jika Anda perlu mengubah banyak karakter, dan itu sederhana.
Sheepy

6
Saya membuat tes di jsperf: jsperf.com/replace-character-by-index - Substr lebih cepat, dan konsisten dari 32bytes hingga 100kb. Saya membatalkan ini dan sama menyakitkannya untuk mengatakan, meskipun ini terasa lebih baik, substr adalah pilihan yang lebih baik untuk string dari berbagai ukuran.
Cory Mawhorter

Ini sangat tidak optimal.
Radko Dinev

Ini adalah solusi cepat yang bagus jika Anda tahu Anda akan menggunakan string kecil. Jika Anda setuju dengan memperpanjang prototipe, maka Anda dapat mencapai perilaku serupa dalam 2 baris:Array.prototype.replace = function(index, val) { this[index] = val; return this; }; 'word'.split('').replace(1, '0').join(''); // returns 'w0rd'
Michael Plautz

29

Dalam string Javascript tidak dapat diubah sehingga Anda harus melakukan sesuatu seperti

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

Untuk mengganti karakter dalam x at i dengan 'h'


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

4
Jelas dan sederhana, tetapi saat ini tidak akan berfungsi dengan emoji (seperti 😀) saat menggunakan splitdanjoin
Hijau

1
Dengan es6 saya pikir bahwa Array. Dari (str) mungkin menjadi pilihan yang lebih baik sekarang, tapi saya datang ke sini dengan pengetahuan itu dan belajar sesuatu yang sama ringkasnya dari Anda jadi terima kasih!
David Kamer

7

One-liner menggunakan String.replace dengan callback (tanpa dukungan emoji):

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

Dijelaskan:

//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

Metode ini baik untuk string panjang kecil tetapi mungkin lambat untuk teks yang lebih besar.

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: Terima kasih atas jawaban yang bagus!

Saya juga mengadaptasinya sedikit untuk membuatnya lebih seperti metode Array.splice (dan mempertimbangkan catatan @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!"

Tidak yakin mengapa ini ditolak. Itu jawaban yang sah. Ini berfungsi seperti yang ditunjukkan. Dan ini konsisten dengan Array.splicefungsionalitas tipe.
Scrimothy

3

Ini bekerja mirip dengan Array.splice:

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

3

Kamu bisa mencoba

var strArr = str.split("");

strArr[0] = 'h';

str = strArr.join("");

2

Jika Anda ingin mengganti karakter dalam string, Anda harus membuat string yang bisa berubah. Ini pada dasarnya adalah array karakter. Anda dapat membuat pabrik:

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

Kemudian Anda dapat mengakses karakter dan seluruh array yang dikonversi menjadi string ketika digunakan sebagai string:

  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

Generalisasi jawaban Afanasii Kurakin, kami memiliki:

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

Mari kita perluas dan jelaskan persamaan reguler dan fungsi replacer:

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

Ekspresi reguler .sama persis dengan satu karakter. Itu gmembuatnya cocok dengan setiap karakter dalam for for. The replacerfungsi disebut diberikan baik karakter asli dan indeks di mana karakter yang dalam string. Kami membuat ifpernyataan sederhana untuk menentukan apakah kami akan kembali origCharatau tidak newChar.


2

Anda dapat memperluas jenis string untuk memasukkan metode 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 "));

Kemudian Anda dapat memanggil fungsi:


1

Saya melakukan fungsi yang melakukan sesuatu yang mirip dengan apa yang Anda minta, memeriksa apakah karakter dalam string adalah dalam array karakter yang tidak diizinkan jika diganti dengan ''

    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

ini mudah dicapai dengan 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

Ini adalah versi yang saya buat jika Anda ingin menata kata atau karakter individual pada indeks mereka dalam reaksi / javascript.

replaceAt( yourArrayOfIndexes, yourString/orArrayOfStrings ) 

Contoh kerja: https://codesandbox.io/s/ov7zxp9mjq

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

Dan inilah metode alternatif lain

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

Dan satu lagi ...

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

Saya tahu ini sudah tua tetapi solusinya tidak bekerja untuk indeks negatif jadi saya menambahkan tambalan untuk itu. semoga membantu seseorang

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

Katakanlah Anda ingin mengganti Kthindeks (indeks berbasis 0) dengan 'Z'. Anda dapat menggunakannya Regexuntuk melakukan ini.

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

Tahu mengapa tag ini tidak berguna?
ksp

Saya belum memeriksa apakah regex ini berfungsi, tapi mungkin itu downvoted karena mungkin jauh lebih cepat untuk membuat string baru, daripada mengkompilasi mesin negara (ekspresi reguler), yang sangat mahal.
Felo Vilches

0

Anda dapat menggunakan fungsi berikut untuk mengganti Characteratau Stringpada posisi tertentu dari sebuah String. Untuk mengganti semua kasus pencocokan berikut, gunakan String.prototype.replaceAllMatches()fungsi.

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

Uji:

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

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

Keluaran:

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

-1

Ini solusi saya menggunakan operator ternary dan map. Lebih mudah dibaca, dapat dikelola, lebih mudah dimengerti jika Anda bertanya kepada saya.

Ini lebih ke es6 dan praktik terbaik.

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

Metode di sini rumit. Saya akan melakukannya dengan cara ini:

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

Ini sesederhana yang didapat.


6
Sebenarnya tidak. Bahkan itu akan menggantikan kemunculan karakter pertama. Masih salah.
Tomáš Zato - Reinstate Monica
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.