Hapus semua kemunculan char dari string

311

Saya bisa menggunakan ini:

String str = "TextX Xto modifyX";
str = str.replace('X','');//that does not work because there is no such character ''

Apakah ada cara untuk menghapus semua kemunculan karakter Xdari sebuah String di Jawa?

Saya mencoba ini dan bukan yang saya inginkan: str.replace('X',' '); //replace with space

evilReiko
sumber
3
Sudahkah Anda mencoba mengganti Strings karakter tunggal?
peter.murray.rust

Jawaban:

523

Coba gunakan overload yang membutuhkan CharSequenceargumen (misalnya, String) daripada char:

str = str.replace("X", "");
LukeH
sumber
2
Argumen pertama adalah ekspresi reguler, terkadang tidak berfungsi seperti yang diharapkan, terutama jika string ini berasal dari input pengguna.
vbezhenar
9
@vsb: Tidak benar. Kedua argumen dari kelebihan itu adalah CharSequence. docs.oracle.com/javase/7/docs/api/java/lang/…
LukeH
Apa yang harus dilakukan jika Xtipe char?
KNU
7
@ Kunal: Saya kira Anda harus toStringterlebih dahulu. Jadi kode Anda akan terlihat sepertistr = str.replace(yourChar.toString(), "");
LukeH
Catatan Anda dapat menggunakan pelepasan unicode, mis. Tidak ada penghapusan karakterstr = str.replace("\uffff", "");
Jaime Hablutzel
42

Menggunakan

public String replaceAll(String regex, String replacement)

akan bekerja.

Penggunaan akan str.replace("X", "");.

Mengeksekusi

"Xlakjsdf Xxx".replaceAll("X", "");

pengembalian:

lakjsdf xx
Michael Wiles
sumber
6
Regex mungkin berlebihan untuk hal ini kecuali Anda dibatasi untuk mendukung Java 1.4 - karena versi 1.5 ada replacekelebihan yang dibutuhkan CharSequence.
LukeH
3
@ Lukas, Ini adalah sumber terekompilasi ke String.replace. Itu menggunakan regex. Saya setuju bahwa regex terasa berat, tetapi itulah yang ada di bawah tenda bahkan untuk jawaban yang diterima di atas. public string replace (CharSequence var1, CharSequence var2) {return Pattern.compile (var1.toString (), 16) .matcher (ini) .replaceAll (Matcher.quoteReplacement (var2.toString ())); }
Perry Tew
24

Jika Anda ingin melakukan sesuatu dengan Java Strings, Commons Lang StringUtils adalah tempat yang tepat untuk melihat.

StringUtils.remove("TextX Xto modifyX", 'X');
Arend v. Reinersdorff
sumber
persis apa yang saya cari, mungkin karena hanya terlihat lebih jelas daripada replace.
Jalur
6
String test = "09-09-2012";
String arr [] = test.split("-");
String ans = "";

for(String t : arr)
    ans+=t;

Ini adalah contoh di mana saya telah menghapus karakter - dari String.

JavaChamp
sumber
4
Ini sangat tidak efisien, terutama dibandingkan dengan jawaban yang diterima.
Erick Robertson
3
Saya pikir jawaban ini berfungsi, tetapi jawaban yang benar lebih pendek dan lebih cepat
evilReiko
2

Saya suka menggunakan RegEx dalam kesempatan ini:

str = str.replace(/X/g, '');

di mana g berarti global sehingga akan melewati seluruh string Anda dan ganti semua X dengan ''; jika Anda ingin mengganti X dan x, Anda cukup mengatakan:

str = str.replace(/X|x/g, '');

(Lihat biola saya di sini: biola )

Gerrit B
sumber
Saya kira ini mungkin berhasil, tetapi jawaban yang benar dijalankan lebih cepat dan lebih pendek, selalu lebih baik untuk menghindari RegEx sebanyak mungkin karena diketahui lebih lambat daripada metode lain
evilReiko
2

Halo, Coba kode ini di bawah ini

public class RemoveCharacter {

    public static void main(String[] args){
        String str = "MXy nameX iXs farXazX";
        char x = 'X';
        System.out.println(removeChr(str,x));
    }

    public static String removeChr(String str, char x){
        StringBuilder strBuilder = new StringBuilder();
        char[] rmString = str.toCharArray();
        for(int i=0; i<rmString.length; i++){
            if(rmString[i] == x){

            } else {
                strBuilder.append(rmString[i]);
            }
        }
        return strBuilder.toString();
    }
}
Raju
sumber
bagaimana Anda melakukan ini jika bukan x kita punya string lain? Solusi bagus!
Mona Jalal
2

Gunakan replaceAll alih-alih ganti

str = str.replaceAll("X,"");

Ini akan memberi Anda jawaban yang diinginkan.

Ayushi Jain
sumber
ganti berakhir menggunakan replaceAll. Lihatlah implementasinya. Ini adalah bagaimana String # replace diimplementasikan:return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
Sal_Vader_808
0
package com.acn.demo.action;

public class RemoveCharFromString {

    static String input = "";
    public static void main(String[] args) {
        input = "abadbbeb34erterb";
        char token = 'b';
        removeChar(token);
    }

    private static void removeChar(char token) {
        // TODO Auto-generated method stub
        System.out.println(input);
        for (int i=0;i<input.length();i++) {
            if (input.charAt(i) == token) {
            input = input.replace(input.charAt(i), ' ');
                System.out.println("MATCH FOUND");
            }
            input = input.replaceAll(" ", "");
            System.out.println(input);
        }
    }
}
harikrishna tekkam
sumber
input = "deletes all blanks too";memberikan "deletesalllankstoo"
Kaplan
0

di sini adalah fungsi lambda yang menghapus semua karakter yang dilewatkan sebagai string

BiFunction<String,String,String> deleteChars = (fromString, chars) -> {
  StringBuilder buf = new StringBuilder( fromString );
  IntStream.range( 0, buf.length() ).forEach( i -> {
    while( i < buf.length() && chars.indexOf( buf.charAt( i ) ) >= 0 )
      buf.deleteCharAt( i );
  } );
  return( buf.toString() );
};

String str = "TextX XYto modifyZ";
deleteChars.apply( str, "XYZ" ); // –> "Text to modify"

Solusi ini memperhitungkan bahwa String yang dihasilkan - berbeda dengan replace()- tidak pernah menjadi lebih besar dari String awal ketika menghapus karakter. Jadi itu menghindari pengalokasian dan penyalinan yang berulang sambil menambahkan karakter ke StringBuilderseperti replace()halnya.
Belum lagi generasi yang tidak berguna Patterndan Matchercontoh replace()yang tidak pernah diperlukan untuk dihapus.
Berbeda dengan replace()solusi ini dapat menghapus beberapa karakter dalam satu gerakan.

Kaplan
sumber
Pemrograman Lambdas / Fungsional sangat populer saat ini tetapi menggunakannya untuk membuat solusi yang 10x lebih lama dari jawaban yang dipilih tidak dapat dibenarkan IMHO, karenanya suara turun.
Volksman
str.replace("…", "")instantiate private Pattern(…)dan kemudian pada panggilan pola yang dihasilkan public String replaceAll(String repl). Jadi panggilan fungsi berikut terjadi: return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString())); - lihat komentar Sal_Vader_808. Semua dalam semua ca 3 kali lebih lama dari solusi lambda pinggul saya . Dan di sini dijelaskan dengan baik mengapa solusi lambda pinggul saya juga lebih cepat: Mengapa Java's String :: replace () begitu lambat?
Kaplan
sendiri : Jika itu benar-benar tentang ukuran solusi, beberapa solusi lain dua kali lebih besar atau solusi yang membutuhkan perpustakaan eksternal akan menjadi kandidat yang lebih cocok untuk dikritik. Perpanjangan bahasa yang telah menjadi bagian dari bahasa tersebut selama bertahun-tahun sejak Java 8 tidak terlalu keren . Masalah umum dengan sistem penilaian adalah, bahwa faktor waktu lebih berat daripada kualitas solusi. Akibatnya, solusi yang lebih baru dan kadang-kadang bahkan lebih baik semakin banyak ditemukan di belakang.
Kaplan
Saya merujuk 10x lebih lama dalam hal kode bukan kecepatan eksekusi. Apa pun yang mengkompilasi pola regex setiap kali dipanggil bisa jauh lebih lambat. Anda benar-benar perlu untuk men-cache pencocokan yang dikompilasi dan menggunakan kembali jika menggunakan regex tersebut pada frekuensi tinggi (OP tidak mengatakan skenario apa yang digunakan itu - mungkin skenario yang jarang terjadi untuk membersihkan data dari pengiriman formulir atau dapat digunakan dengan ketat loop disebut 1000 kali per detik).
Volksman
Berkenaan dengan masalah kinerja saya menambahkan jawaban baru yang menjalankan patokan cepat pada berbagai jawaban yang diberikan. Jika OP sering melakukan operasi ini maka mereka harus menghindari opsi String.replace () karena kompilasi ulang pola regex di bawah tenda sangat mahal.
Volksman
0

Evaluasi jawaban utama dengan tolok ukur kinerja yang menegaskan kekhawatiran bahwa jawaban yang dipilih saat ini membuat operasi regex mahal di bawah tenda

Sampai saat ini jawaban yang diberikan datang dalam 3 gaya utama (mengabaikan jawaban JavaScript;)):

  • Gunakan String.replace (charsToDelete, ""); yang menggunakan regex di bawah tenda
  • Gunakan Lambda
  • Gunakan implementasi Java sederhana

Dalam hal ukuran kode jelas String.replace adalah yang paling singkat. Implementasi Java sederhana sedikit lebih kecil dan lebih bersih (IMHO) daripada Lambda (jangan salah paham - Saya sering menggunakan Lambdas jika sesuai)

Kecepatan eksekusi adalah, dalam urutan tercepat ke paling lambat: implementasi Java sederhana, Lambda dan kemudian String.replace () (yang memanggil regex).

Sejauh ini, implementasi tercepat adalah implementasi Java sederhana yang disetel sehingga mengalokasi buffer StringBuilder ke panjang hasil maksimal yang mungkin dan kemudian hanya menambahkan karakter ke buffer yang tidak ada dalam string "karakter yang akan dihapus". Ini menghindari setiap realokasi yang akan terjadi untuk panjang Strings> 16 chars (alokasi default untuk StringBuilder) dan menghindari hit kinerja "slide kiri" untuk menghapus karakter dari salinan string yang terjadi adalah implementasi Lambda.

Kode di bawah ini menjalankan tes benchmark sederhana, menjalankan setiap implementasi 1.000.000 kali dan mencatat waktu yang berlalu.

Hasil yang tepat bervariasi setiap kali dijalankan tetapi urutan kinerja tidak pernah berubah:

Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms

Implementasi Lambda (seperti yang disalin dari jawaban Kaplan) mungkin lebih lambat karena melakukan "pergeseran ke kiri oleh satu" dari semua karakter di sebelah kanan karakter yang dihapus. Ini jelas akan menjadi lebih buruk untuk string yang lebih panjang dengan banyak karakter yang membutuhkan penghapusan. Juga mungkin ada beberapa overhead dalam implementasi Lambda itu sendiri.

Implementasi String.replace, menggunakan regex dan melakukan regex "kompilasi" pada setiap panggilan. Optimasi ini akan menggunakan regex secara langsung dan cache pola yang dikompilasi untuk menghindari biaya kompilasi setiap kali.

package com.sample;

import java.util.function.BiFunction;
import java.util.stream.IntStream;

public class Main {

    static public String deleteCharsSimple(String fromString, String charsToDelete)
    {
        StringBuilder buf = new StringBuilder(fromString.length()); // Preallocate to max possible result length
        for(int i = 0; i < fromString.length(); i++)
            if (charsToDelete.indexOf(fromString.charAt(i)) < 0)
                buf.append(fromString.charAt(i));   // char not in chars to delete so add it
        return buf.toString();
    }

    static public String deleteCharsLambda(String fromString1, String charsToDelete)
    {
        BiFunction<String, String, String> deleteChars = (fromString, chars) -> {
            StringBuilder buf = new StringBuilder(fromString);
            IntStream.range(0, buf.length()).forEach(i -> {
                while (i < buf.length() && chars.indexOf(buf.charAt(i)) >= 0)
                    buf.deleteCharAt(i);
            });
            return (buf.toString());
        };

        return deleteChars.apply(fromString1, charsToDelete);
    }

    static public String deleteCharsReplace(String fromString, String charsToDelete)
    {
        return fromString.replace(charsToDelete, "");
    }


    public static void main(String[] args)
    {
        String str = "XXXTextX XXto modifyX";
        String charsToDelete = "X";  // Should only be one char as per OP's requirement

        long start, end;

        System.out.println("Start simple");
        start = System.currentTimeMillis();

        for (int i = 0; i < 1000000; i++)
            deleteCharsSimple(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));

        System.out.println("Start lambda");
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++)
            deleteCharsLambda(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));

        System.out.println("Start replace");
        start = System.currentTimeMillis();

        for (int i = 0; i < 1000000; i++)
            deleteCharsReplace(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));
    }
}
Volksman
sumber
Jika fungsi lambda disebut seperti yang dimaksudkan untuk dilakukan, waktunya adalah sebagai berikut (tidak ada yang membungkus fungsi lambda menjadi fungsi anggota) . Selanjutnya deleteCharsReplace Anda () salah diterapkan: ia menggantikan satu String "XYZ" dan tidak seperti yang disyaratkan 'X', 'Y' dan 'Z' apa yang fromString.replace("X", "").replace("Y", "").replace("Z", "");dibutuhkan. Sekarang kita mendapatkan waktu yang tepat: Mulai waktu sederhana: 759 | Mulai lambda Waktu: 1092 | Mulai deleteCharsLambda () Waktu: 1420 | Mulai ganti yang diperbaiki Waktu: 4636
Kaplan
"tidak ada yang membungkus fungsi lambda menjadi fungsi anggota" - kecuali untuk tujuan memanggilnya dalam skenario benchmark sehingga konsisten dengan cara implementasi lainnya disebut.
Volksman
Saya baru menyadari bahwa OP bertanya tentang menghapus semua kemunculan karakter tunggal tetapi jawaban Anda mengubah ruang lingkup untuk berurusan dengan serangkaian karakter. Implementasi jawaban "diterima" yang saya gunakan tidak dan tidak pernah dimaksudkan untuk melayani beberapa karakter. Jadi saya telah memperbarui patokan di atas untuk mencerminkan ini dan waktu patokan. BTW jika Anda ingin menambah ruang lingkup untuk mendukung banyak karakter yang menelepon, ganti beberapa kali adalah mahal. Lebih baik beralih ke satu panggilan untuk menggantiAll ("[XYZ]", "")
Volksman
Fungsi seperti yang ditunjukkan dalam solusi hanya diinisiasi sekali ketika dipanggil. Untuk membungkus fungsi secara tambahan ke pemanggilan fungsi ke fungsi anggota hanya memiliki efek untuk mendistorsi tolok ukur.
Kaplan
Hampir tidak mungkin untuk melakukan patokan dengan cepat metode durasi cepat dengan membuat satu panggilan karena varians dari setiap panggilan sangat tinggi. Jadi pembandingan biasanya melibatkan banyak panggilan berulang ke metode yang sama dan kemudian total waktu dievaluasi untuk membandingkan dengan total waktu dari alternatif (atau untuk menghitung rata-rata jika diperlukan) ..
Volksman
0

Anda harus meletakkan karakter yang harus dihapus di dalam tanda kurung siku selama waktu penggantian. Contoh kode adalah sebagai berikut:

String s = "$116.42".replaceAll("[$]", "");
Chaklader Asfak Arefe
sumber
-3

Anda dapat menggunakan str = str.replace("X", "");seperti yang disebutkan sebelumnya dan Anda akan baik-baik saja. Karena informasi Anda ''bukan karakter yang kosong (atau valid) tetapi '\0'.

Jadi Anda bisa menggunakannya str = str.replace('X', '\0');sebagai gantinya.

Foivos
sumber
9
ini tidak benar. '\ 0' akan menghasilkan karakter nol yang sebenarnya. str.replace ('X', '\ 0') setara dengan str.replace ("X", "\ u0000") yang sama sekali tidak seperti yang diinginkan OP
Andrey