Apakah ada metode sambungan untuk string?

92

Javascript splicehanya bekerja dengan array. Apakah ada metode serupa untuk string? Atau haruskah saya membuat fungsi kustom saya sendiri?

Metode substr(), dan substring()hanya akan mengembalikan string yang diekstrak dan tidak mengubah string aslinya. Yang ingin saya lakukan adalah menghapus beberapa bagian dari string saya dan menerapkan perubahan ke string asli. Selain itu, metode replace()ini tidak akan berfungsi dalam kasus saya karena saya ingin menghapus bagian yang dimulai dari indeks dan berakhir di indeks lain, persis seperti yang dapat saya lakukan dengan splice()metode tersebut. Saya mencoba mengubah string saya menjadi array, tetapi ini bukan metode yang rapi.

ProllyGeek
sumber
str.splitmungkin fungsi yang Anda cari: google.com/#q=javascript+string+split
Anderson Green
1
Ada apa dengan str = str.slice()?
elclanrs
1
Sepertinya masalah XY, apa yang sebenarnya Anda coba lakukan? String tidak diteruskan oleh referensi, tidak seperti array dan objek, jadi Anda tidak mengubah string, Anda membuat string baru atau menetapkan ulang string baru ke string lama.
elclanrs
6
return string.slice(0, startToSplice) + string.slice(endToSplice);, tidak?
raina77ow

Jawaban:

90

Lebih cepat untuk memotong string dua kali, seperti ini:

function spliceSlice(str, index, count, add) {
  // We cannot pass negative indexes directly to the 2nd slicing operation.
  if (index < 0) {
    index = str.length + index;
    if (index < 0) {
      index = 0;
    }
  }

  return str.slice(0, index) + (add || "") + str.slice(index + count);
}

daripada menggunakan split diikuti dengan join (metode Kumar Harsh), seperti ini:

function spliceSplit(str, index, count, add) {
  var ar = str.split('');
  ar.splice(index, count, add);
  return ar.join('');
}

Berikut adalah jsperf yang membandingkan dua dan beberapa metode lainnya. (jsperf telah turun selama beberapa bulan sekarang. Harap sarankan alternatif di komentar.)

Meskipun kode di atas mengimplementasikan fungsi yang mereproduksi fungsionalitas umumsplice , mengoptimalkan kode untuk kasus yang disajikan oleh penanya (yaitu, tidak menambahkan apa pun ke string yang dimodifikasi) tidak mengubah kinerja relatif dari berbagai metode.

Louis
sumber
3
Anda dapat menambahkan ini secara global dengan: String.prototype.splice = function (index, count, add) { return this.slice(0, index) + (add || "") + this.slice(index + count); } Ingatlah bahwa ini tidak berfungsi persis sama dengan metode sambungan array karena string tidak dapat diubah (Anda tidak dapat memodifikasinya setelah dibuat). Jadi penggunaannya akan seperti:var s="ss"; s = s.splice(0,1,"t");
William Neely
@WilliamNeely: var StringUtils={'StringSplice':/*func def*/};akan menjadi standar untuk manipulasi string seperti yang Anda katakan bahwa itu tidak dapat diubah.
Tn. Polywhirl
spliceSlice dan spliceSplit tidak berfungsi sama karena Array.prototype.splice menerima indeks negatif: jsfiddle.net/sykteho6/5 .
Martijn
1
@Mzialla Terima kasih, saya telah menambahkan kode untuk mengurusnya.
Louis
Membuat temp vars dan memasukkan tempat untuk kesalahan off-by-one, belum lagi kode yang membutuhkan waktu lebih lama untuk diproses oleh manusia dibandingkan dengan split (""). Splice (...). Join ("") adalah tradeoff yang pantas dipertimbangkan. Masalah kecepatan hanya menjadi masalah jika itu masalah.
ballenf
16

Sunting

Ini tentu saja bukan cara terbaik untuk "menyambung" string, saya telah memberikan ini sebagai contoh bagaimana implementasinya akan, yang cacat dan sangat jelas dari split (), splice () dan join (). Untuk implementasi yang jauh lebih baik, lihat metode Louis .


Tidak, tidak ada yang namanya a String.splice, tetapi Anda dapat mencoba ini:

newStr = str.split(''); // or newStr = [...str];
newStr.splice(2,5);
newStr = newStr.join('');

Saya menyadari tidak ada splicefungsi seperti di Array, jadi Anda harus mengubah string menjadi array. Nasib sial...

kumarharsh
sumber
dalam kasus saya, saya sedang mengerjakan string dinamis jadi saya perlu menentukan indeks dan bukan nilai karakter.
ProllyGeek
Ya, sayangnya itu benar. Tetapi Anda bisa mendapatkan indeks karakter dengan menggunakan String.prototype.indexOf as"asdsd".indexOf('s');
kumarharsh
3
Alih-alih menggunakan str.split, Anda dapat menggunakan sintaks spread ES6 seperti ini:[...str]
robbie
5

Inilah kari kecil yang enak yang memberikan keterbacaan yang lebih baik (IMHO):

Tanda tangan fungsi kedua identik dengan Array.prototype.splicemetode.

function mutate(s) {
    return function splice() {
        var a = s.split('');
        Array.prototype.splice.apply(a, arguments);
        return a.join('');
    };
}

mutate('101')(1, 1, '1');

Saya tahu sudah ada jawaban yang diterima, tapi semoga bermanfaat.

Cody
sumber
1
Np. Anda bahkan dapat mengabstraksi ini untuk memungkinkan, katakanlah, 'method'parameter opsional sehingga Anda bisa meneruskan Array.prototype[method]dan memperlakukan string sepenuhnya seperti array. Juga, dengan satu ini saja, Anda bisa abstrak proses yang sebenarnya untuk fungsi lain - dan jika tidak ada tali, mengembalikan fungsi yang akan membawa tali dan membalikkan kari: mutate()(1, 1, '1')('101'); Anda bahkan bisa duckType argumen untuk menyingkirkan kari dari permintaan kosong - bahkan merangkum metode itu sendiri. Jika Anda membutuhkan barang ini, Anda mungkin ingin melihat ke Pola Perintah . Ludah saja di sini.
Cody
3

Saya ingin menawarkan alternatif yang lebih sederhana untuk metode Kumar / Cody dan Louis. Pada semua tes yang saya jalankan, itu bekerja secepat metode Louis (lihat tes biola untuk benchmark).

String.prototype.splice = function(startIndex,length,insertString){
    return this.substring(0,startIndex) + insertString + this.substring(startIndex + length);
};

Anda bisa menggunakannya seperti ini:

var creditCardNumber = "5500000000000004";
var cardSuffix = creditCardNumber.splice(0,12,'****');
console.log(cardSuffix);  // output: ****0004

Lihat Hasil Tes: https://jsfiddle.net/0quz9q9m/5/

Timothy Kanski
sumber
Anda setidaknya harus melakukan `+ (insertString ||" ") +` daripada `+ insertString + , otherwise the third argument is not optional. This implementation also doesn't take care of startIndex <0` tidak seperti saran lainnya. Contoh penggunaan yang bagus, meskipun
YakovL
3

Tampaknya ada banyak kebingungan yang hanya diatasi di komentar oleh elclanrs dan raina77ow, jadi izinkan saya memposting jawaban klarifikasi.

Klarifikasi

Dari " string.splice" orang mungkin mengharapkannya, seperti yang untuk array:

  • menerima hingga 3 argumen: posisi awal, panjang dan (opsional) penyisipan (string)
  • mengembalikan bagian yang dipotong
  • memodifikasi string asli

Masalahnya, persyaratan 3d tidak dapat dipenuhi karena string tidak dapat diubah (terkait: 1 , 2 ), saya telah menemukan komentar paling berdedikasi di sini :

Dalam JavaScript, string adalah tipe nilai primitif dan bukan objek ( spesifikasi ). Bahkan, pada ES5, mereka salah satu dari hanya 5 jenis nilai bersama null, undefined, numberdan boolean. String ditetapkan berdasarkan nilai dan bukan dengan referensi dan diteruskan seperti itu. Jadi, string bukan hanya tidak bisa diubah, tapi juga sebuah nilai . Mengubah string "hello"menjadi "world"seperti memutuskan bahwa mulai sekarang angka 3 adalah angka 4 ... itu tidak masuk akal.

Jadi, dengan pertimbangan itu, orang mungkin mengharapkan " string.splice" untuk hanya:

  • menerima hingga 2 argumen: posisi awal, panjang (penyisipan tidak masuk akal karena string tidak diubah)
  • mengembalikan bagian yang dipotong

yaitu apa yang substrdilakukannya; atau, sebagai alternatif,

  • menerima hingga 3 argumen: posisi awal, panjang dan (opsional) penyisipan (string)
  • mengembalikan string yang dimodifikasi (tanpa bagian yang dipotong dan dengan penyisipan)

yang merupakan subjek dari bagian selanjutnya.

Solusi

Jika Anda peduli tentang pengoptimalan, Anda mungkin harus menggunakan implementasi Mike:

String.prototype.splice = function(index, count, add) {
    if (index < 0) {
        index += this.length;
        if (index < 0)
            index = 0;
    }
    return this.slice(0, index) + (add || "") + this.slice(index + count);
}

Memperlakukan indeks di luar batas mungkin berbeda-beda. Bergantung pada kebutuhan Anda, Anda mungkin menginginkan:

    if (index < 0) {
        index += this.length;
        if (index < 0)
            index = 0;
    }
    if (index >= this.length) {
        index -= this.length;
        if (index >= this.length)
            index = this.length - 1;
    }

atau bahkan

    index = index % this.length;
    if (index < 0)
        index = this.length + index;

Jika Anda tidak peduli dengan kinerja, Anda mungkin ingin menyesuaikan saran Kumar yang lebih langsung:

String.prototype.splice = function(index, count, add) {
    var chars = this.split('');
    chars.splice(index, count, add);
    return chars.join('');
}

Performa

Perbedaan penampilan meningkat drastis dengan panjang senar. jsperf menunjukkan , bahwa untuk string dengan panjang 10 solusi terakhir (pemisahan & penggabungan) dua kali lebih lambat dari solusi sebelumnya (menggunakan slice), untuk string 100 huruf x5 dan untuk string 1000 huruf x50, di Ops / detik itu:

                      10 letters   100 letters   1000 letters
slice implementation    1.25 M       2.00 M         1.91 M
split implementation    0.63 M       0.22 M         0.04 M

perhatikan bahwa saya telah mengubah argumen 1 dan 2 saat berpindah dari 10 huruf menjadi 100 huruf (tetap saja saya terkejut bahwa tes untuk 100 huruf berjalan lebih cepat dari itu untuk 10 huruf).

YakovL
sumber
2

Cukup gunakan substr untuk string

ex.

var str = "Hello world!";
var res = str.substr(1, str.length);

Hasil = ello dunia!

Dinesh Patil
sumber
1

Jadi, apa pun menambahkan metode sambatan ke prototipe String tidak dapat berfungsi transparan untuk spesifikasi ...

Mari kita lakukan seseorang memperpanjangnya:

String.prototype.splice = function(...a){
    for(var r = '', p = 0, i = 1; i < a.length; i+=3)
        r+= this.slice(p, p=a[i-1]) + (a[i+1]||'') + this.slice(p+a[i], p=a[i+2]||this.length);
    return r;
}
  • Setiap 3 grup args "menyisipkan" dalam gaya sambungan.
  • Khususnya jika ada lebih dari satu 3 kelompok argumentasi, akhir setiap pemotongan akan menjadi awal berikutnya.
    • '0123456789'.splice (4,1,' four ', 8,1,' eighth '); // kembali '0123fourth567eighth9'
  • Anda dapat menghapus atau membidik argumen terakhir di setiap grup (yang diperlakukan sebagai "tidak ada yang disisipkan")
    • '0123456789'.splice (-4,2); // kembalikan '0123459'
  • Anda dapat menghapus semua kecuali argumen pertama di grup terakhir (yang diperlakukan sebagai "potong semua setelah posisi argumen pertama")
    • '0123456789'.splice (0,2, null, 3,1, null, 5,2,' / ', 8); // kembali '24 / 7 '
  • jika Anda lulus lebih dari satu, Anda HARUS memeriksa sendiri jenis posisi urutan kiri-ke-kanan!
  • Dan jika Anda tidak mau, JANGAN gunakan seperti ini:
    • '0123456789'.splice (4, -3,' what? '); // kembalikan "0123what? 123456789"
Fedor Tykmakov
sumber
0

Metode jawaban Louis , sebagai Stringfungsi prototipe:

String.prototype.splice = function(index, count, add) {
  if (index < 0) {
    index = this.length + index;
    if (index < 0) {
      index = 0;
    }
  }
  return this.slice(0, index) + (add || "") + this.slice(index + count);
}

Contoh:

 > "Held!".splice(3,0,"lo Worl")
 < "Hello World!"
Mike Godin
sumber
0

Metode spliceSlice Louis gagal ketika nilai tambah adalah 0 atau nilai salah lainnya, berikut perbaikannya:

function spliceSlice(str, index, count, add) {
  if (index < 0) {
    index = str.length + index;
    if (index < 0) {
      index = 0;
    }
  }
  const hasAdd = typeof add !== 'undefined';
  return str.slice(0, index) + (hasAdd ? add : '') + str.slice(index + count);
}
Maryus Martsyalis
sumber
0

Saya memecahkan masalah saya menggunakan kode ini, merupakan pengganti sambungan yang hilang.

let str = "I need to remove a character from this";
let pos = str.indexOf("character")

if(pos>-1){
  let result = str.slice(0, pos-2) + str.slice(pos, str.length);
  console.log(result) //I need to remove character from this 
}

Saya perlu menghapus karakter sebelum / setelah kata tertentu, setelah Anda mendapatkan posisi string dibagi menjadi dua dan kemudian disusun ulang dengan menghapus karakter secara fleksibel menggunakan offset bersama pos

Ray Remnant
sumber