ลบ char ทั้งหมดออกจากสตริง


311

ฉันสามารถใช้สิ่งนี้:

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

มีวิธีลบอักขระที่เกิดขึ้นทั้งหมดXจากสตริงใน Java หรือไม่?

ฉันลองสิ่งนี้และไม่ใช่สิ่งที่ฉันต้องการ: str.replace('X',' '); //replace with space


3
คุณได้ลองแทนที่สตริงอักขระเดียวหรือไม่
peter.murray.rust

คำตอบ:


523

ลองใช้โอเวอร์โหลดที่รับCharSequenceอาร์กิวเมนต์ (เช่นString) แทนchar:

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

2
อาร์กิวเมนต์แรกคือนิพจน์ทั่วไปบางครั้งมันจะไม่ทำงานตามที่คาดไว้โดยเฉพาะอย่างยิ่งถ้าสตริงนี้มาจากอินพุตของผู้ใช้
vbezhenar

9
@vsb: ไม่จริง CharSequenceข้อโต้แย้งทั้งสองเกินเฉพาะที่เป็น docs.oracle.com/javase/7/docs/api/java/lang/…
LukeH

จะทำอย่างไรในกรณีที่Xเป็นถ่านประเภท?
KNU

7
@Kunal: ฉันเดาว่าคุณต้องใช้toStringมันก่อน ดังนั้นโค้ดของคุณจะเป็นอย่างไรstr = str.replace(yourChar.toString(), "");
LukeH

โปรดทราบว่าคุณสามารถใช้การหลบหนีแบบ Unicode เช่นไม่มีการลบอักขระที่ไม่ใช่ตัวอักษรstr = str.replace("\uffff", "");
Jaime Hablutzel

42

การใช้

public String replaceAll(String regex, String replacement)

จะทำงาน.

การใช้งานจะเป็น str.replace("X", "");การใช้งานจะเป็น

การดำเนินการ

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

ผลตอบแทน:

lakjsdf xx

6
Regex อาจ overkill สำหรับเรื่องนี้คือถ้าคุณกำลัง จำกัด ให้การสนับสนุน Java 1.4 - ตั้งแต่รุ่น 1.5 มีเกินพิกัดที่ใช้ง่ายreplace CharSequence
ลุ

3
@LukeH นี่คือแหล่งที่ถอดรหัสแล้วไปยัง String.replace มันใช้ regex ฉันยอมรับว่ามัน regex รู้สึกหนัก แต่นั่นคือสิ่งที่อยู่ภายใต้ประทุนแม้สำหรับคำตอบที่ได้รับการยอมรับข้างต้น String สาธารณะแทนที่ (CharSequence var1, CharSequence var2) {return Pattern.compile (var1.toString (), 16) .atcher (นี่) .replaceAll (Matcher.quoteReplacement (var2.toString ()) }
Perry Tew

24

หากคุณต้องการทำอะไรกับ Java Strings คอมมอนส์ Lang StringUtilsเป็นสถานที่ที่เหมาะสำหรับการดู

StringUtils.remove("TextX Xto modifyX", 'X');

replaceสิ่งที่ผมมองหาอาจจะเป็นเพราะมันก็มีลักษณะที่ชัดเจนมากกว่า
บรรทัด

6
String test = "09-09-2012";
String arr [] = test.split("-");
String ans = "";

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

นี่คือตัวอย่างที่ฉันลบตัวละคร - ออกจาก String


4
มันไม่มีประสิทธิภาพมากโดยเฉพาะเมื่อเปรียบเทียบกับคำตอบที่ยอมรับ
Erick Robertson

3
ฉันคิดว่าคำตอบนี้ใช้ได้ผล แต่คำตอบที่ถูกต้องนั้นสั้นกว่าและเร็วกว่า
evilReiko

2

ฉันชอบใช้ RegEx ในโอกาสนี้:

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

โดยที่ g หมายถึง global ดังนั้นจะผ่านสตริงทั้งหมดของคุณและแทนที่ X ทั้งหมดด้วย ''; หากคุณต้องการแทนที่ทั้ง X และ x คุณเพียงแค่พูดว่า:

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

(ดูซอของฉันที่นี่: ซอ )


ฉันเดาว่านี่อาจจะใช้ได้ แต่คำตอบที่ถูกต้องจะทำงานได้เร็วและสั้นกว่าเสมอเพื่อหลีกเลี่ยง RegEx ให้มากที่สุดเท่าที่จะทำได้ช้ากว่าวิธีอื่น ๆ
evilReiko

2

สวัสดีลองรหัสนี้ด้านล่าง

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

คุณจะทำอย่างไรถ้าเรามีสตริงอื่นแทน x ทางออกที่ดี!
Mona Jalal

2

ใช้ replaceAll แทนการแทนที่

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

สิ่งนี้จะให้คำตอบที่ต้องการ


แทนที่จบลงด้วยการใช้ replaceAll ดูการใช้งาน นี่คือวิธีการใช้งาน String # replace: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);
        }
    }
}

input = "deletes all blanks too";ให้ "deletesalllankstoo"
Kaplan

0

นี่คือฟังก์ชั่นแลมบ์ดาซึ่งจะลบอักขระทั้งหมดที่ส่งผ่านเป็นสตริง

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"

วิธีการแก้ปัญหานี้จะคำนึงถึงจำนวนของสตริงที่เกิด - ซึ่งแตกต่างจากreplace()- จะไม่ใหญ่กว่าสตริงเริ่มต้นเมื่อลบอักขระ ดังนั้นจึงหลีกเลี่ยงการจัดสรรและคัดลอกซ้ำ ๆ ในขณะที่ผนวกอักขระที่ชาญฉลาดกับสิ่งStringBuilderที่replace()ทำ
ไม่พูดถึงการสร้างPatternและMatcherอินสแตนซ์replace()ที่ไม่มีจุดหมายในสิ่งที่ไม่จำเป็นสำหรับการลบ
ข้อแตกต่างของreplace()โซลูชันนี้สามารถลบอักขระได้หลายตัวในคราวเดียว


ตอนนี้แลมบ์ดา / ฟังก์ชั่นการเขียนโปรแกรมเป็นสิ่งที่ทันสมัยมาก แต่การใช้มันเพื่อสร้างโซลูชันที่ยาวกว่าคำตอบที่เลือก 10 เท่านั้นไม่สามารถพิสูจน์ได้ว่า IMHO เป็นเหตุผลที่ทำให้การลงคะแนนเสียง
Volksman

str.replace("…", "")instantiates และจากนั้นในการสร้างรูปแบบการโทรprivate Pattern(…) public String replaceAll(String repl)ดังนั้นการเรียกใช้ฟังก์ชันต่อไปนี้จึงเกิดขึ้น: return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString())); - ดูความคิดเห็น Sal_Vader_808 ทั้งหมดในทุก ca นานกว่าโซลูชันฮิปแลมด้าของฉัน 3 เท่า และนี่ก็จะมีการอธิบายอย่างว่าทำไมฉันสะโพกแก้ปัญหาแลมบ์ดาก็ยังเร็วขึ้น: ทำไมของ Java String :: แทนที่ () เพื่อให้ช้า?
Kaplan

ในสิ่งที่ตัวเอง : ถ้ามันเกี่ยวกับขนาดของโซลูชันโซลูชันอื่น ๆ ที่ใหญ่เป็นสองเท่าหรือโซลูชันที่ต้องใช้ไลบรารีภายนอกจะเหมาะสมกว่าสำหรับการวิจารณ์ ส่วนขยายของภาษาที่ได้เป็นส่วนหนึ่งของภาษาสำหรับปีนับตั้งแต่ Java 8 ไม่ได้จริงๆสะโพก ปัญหาทั่วไปเกี่ยวกับระบบการให้คะแนนคือปัจจัยเวลามีน้ำหนักมากกว่าคุณภาพของโซลูชันอย่างมาก เป็นผลให้ยิ่งทันสมัยและบางครั้งการแก้ปัญหาที่ดียิ่งขึ้นถูกพบมากขึ้นในด้านหลังที่สาม
Kaplan

ฉันหมายถึง 10x อีกต่อไปในแง่ของรหัสไม่ความเร็ว อะไรก็ตามที่รวบรวมรูปแบบ regex ทุกครั้งที่มีการเรียกใช้นั้นจะช้ากว่ามาก คุณจะต้องแคชตัวจับคู่ที่คอมไพล์แล้วนำมาใช้ใหม่หากใช้ regex ที่ความถี่สูง (OP ไม่ได้บอกว่าใช้สถานการณ์อะไร - อาจเป็นสถานการณ์ที่หายากในการล้างข้อมูลจากการส่งแบบฟอร์มหรืออาจใช้แบบ จำกัด วนซ้ำถูกเรียก 1,000 ครั้งครั้งที่สอง)
Volksman

ในเรื่องที่เกี่ยวกับประสิทธิภาพฉันได้เพิ่มคำตอบใหม่ซึ่งเรียกใช้เกณฑ์มาตรฐานอย่างรวดเร็วเกี่ยวกับคำตอบที่หลากหลายที่มีให้ หาก OP ทำการดำเนินการนี้บ่อยครั้งพวกเขาควรหลีกเลี่ยงตัวเลือก String.replace () เนื่องจากการคอมไพล์ซ้ำของรูปแบบ regex ภายใต้ประทุนมีค่าใช้จ่ายสูงมาก
Volksman

0

การประเมินคำตอบหลักด้วยเกณฑ์มาตรฐานประสิทธิภาพซึ่งยืนยันความกังวลว่าคำตอบที่เลือกในปัจจุบันทำให้การดำเนินการ regex ราคาแพงภายใต้ประทุน

ในวันที่คำตอบที่ให้มามี 3 รูปแบบหลัก (ละเว้นคำตอบ JavaScript;)):

  • ใช้ String.replace (charsToDelete, ""); ซึ่งใช้ regex ภายใต้ประทุน
  • ใช้แลมบ์ดา
  • ใช้การติดตั้ง Java อย่างง่าย

ในแง่ของขนาดรหัสอย่างชัดเจน String.replace เป็นตัวย่อที่สุด การติดตั้ง Java อย่างง่ายมีขนาดเล็กกว่าและสะอาดกว่า (มากกว่า IMHO) มากกว่า Lambda (อย่าเข้าใจฉันผิด - ฉันใช้ Lambdas บ่อยครั้งในที่ที่เหมาะสม)

ความเร็วในการประมวลผลคือช้าที่สุดไปจนถึงช้าที่สุด: การติดตั้ง Java อย่างง่ายแลมบ์ดาแล้วตามด้วย String.replace () (ที่เรียกใช้ regex)

การใช้งานที่เร็วที่สุดคือการปรับใช้ Java อย่างง่ายเพื่อให้สามารถจัดสรรบัฟเฟอร์ StringBuilder ล่วงหน้าให้กับความยาวผลลัพธ์สูงสุดที่เป็นไปได้จากนั้นจึงผนวกตัวอักษรต่อท้ายบัฟเฟอร์ที่ไม่ได้อยู่ในสตริง "ตัวอักษรเพื่อลบ" สิ่งนี้จะหลีกเลี่ยงการจัดสรรใหม่ที่จะเกิดขึ้นสำหรับ Strings> 16 chars ที่มีความยาว (การจัดสรรเริ่มต้นสำหรับ StringBuilder) และจะหลีกเลี่ยงการทำงานที่ "ภาพนิ่งซ้าย" ในการลบอักขระจากการคัดลอกสตริงที่เกิดขึ้นคือการนำ Lambda

โค้ดด้านล่างนี้ทำการทดสอบเกณฑ์มาตรฐานอย่างง่ายโดยเรียกใช้การติดตั้ง 1,000,000 ครั้งและบันทึกเวลา

ผลลัพธ์ที่แน่นอนแตกต่างกันไปในการทำงานแต่ละครั้ง แต่ลำดับของประสิทธิภาพไม่เคยเปลี่ยนแปลง:

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

การปรับใช้แลมบ์ดา (ดังที่คัดลอกมาจากคำตอบของ Kaplan) อาจช้าลงเพราะดำเนินการ "เลื่อนซ้ายหนึ่ง" ของตัวละครทั้งหมดไปทางขวาของตัวละครที่ถูกลบ เห็นได้ชัดว่านี่จะแย่ลงสำหรับสตริงที่ยาวขึ้นซึ่งมีตัวละครจำนวนมากที่ต้องการลบ นอกจากนี้ยังอาจมีค่าใช้จ่ายในการใช้งานแลมบ์ดาเอง

การใช้งาน String.replace ใช้ regex และทำการ "คอมไพล์" regex ที่การโทรแต่ละครั้ง การเพิ่มประสิทธิภาพของสิ่งนี้จะใช้ regex โดยตรงและแคชรูปแบบการรวบรวมเพื่อหลีกเลี่ยงค่าใช้จ่ายในการรวบรวมในแต่ละครั้ง

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

หากฟังก์ชั่นแลมบ์ดาจะเรียกว่าเป็นมันมีจุดมุ่งหมายที่จะทำเวลาที่ต่อไปนี้(ไม่มีตัดฟังก์ชั่นแลมบ์ดาในการทำงานของสมาชิก) นอกจากนี้ deleteCharsReplace () ของคุณมีการใช้งานที่ไม่ถูกต้อง: มันแทนที่หนึ่งสตริง "XYZ" และไม่จำเป็นต้องเป็น 'X', 'Y' และ 'Z' ตามที่ fromString.replace("X", "").replace("Y", "").replace("Z", "");ต้องการ ตอนนี้เราได้เวลาที่ถูกต้อง: เริ่มเวลาง่ายๆ: 759 | เริ่มแลมบ์ดาเวลา: 1092 | เริ่ม deleteCharsLambda () เวลา: 1420 | เริ่มแทนที่เวลาที่แก้ไข: 4636
Kaplan

"ไม่มีใครล้อมฟังก์ชั่นแลมบ์ดาไว้ในฟังก์ชั่นสมาชิก" - ยกเว้นจุดประสงค์ของการเรียกมันในสถานการณ์มาตรฐานเพื่อให้สอดคล้องกับวิธีการใช้งานอื่น ๆ ที่เรียกว่า
Volksman

ฉันเพิ่งรู้ว่า OP ถามเกี่ยวกับการลบอักขระทั้งหมดที่เกิดขึ้นเพียงครั้งเดียวแต่คำตอบของคุณเปลี่ยนขอบเขตเพื่อจัดการกับชุดอักขระ การใช้งานคำตอบ "ยอมรับ" ที่ฉันใช้ไม่ได้และไม่ได้มีไว้เพื่อรองรับอักขระหลายตัว ดังนั้นฉันจึงอัปเดตเกณฑ์มาตรฐานข้างต้นเพื่อสะท้อนถึงสิ่งนี้และเวลามาตรฐาน BTW ถ้าคุณต้องการเพิ่มขอบเขตเพื่อรองรับการโทรหลายตัวอักษรแทนหลายครั้งมีค่าใช้จ่าย ดีกว่าที่จะเปลี่ยนเป็นสายเดียวเพื่อแทนที่ทั้งหมด ("[XYZ]", "")
Volksman

ฟังก์ชั่นตามที่แสดงในการแก้ปัญหานั้นจะถูก inited เพียงครั้งเดียวเมื่อมีการเรียก เมื่อต้องการรวมนิยามของฟังก์ชันเพิ่มเติมเข้ากับการเรียกใช้ฟังก์ชันในฟังก์ชันสมาชิกจะมีผลต่อการบิดเบือนมาตรฐานเท่านั้น
Kaplan

มันแทบเป็นไปไม่ได้เลยที่จะวัดมาตรฐานระยะเวลาด่วนอย่างเหมาะสมด้วยการโทรครั้งเดียวเนื่องจากความแปรปรวนของการโทรแต่ละครั้งนั้นสูงมาก ดังนั้นการเปรียบเทียบจึงมักจะทำการโทรซ้ำหลายครั้งในวิธีเดียวกันจากนั้นเวลาทั้งหมดจะถูกประเมินเพื่อเปรียบเทียบกับเวลาทั้งหมดของทางเลือก (หรือเพื่อคำนวณค่าเฉลี่ยหากจำเป็น) ..
Volksman

0

คุณจะต้องใส่อักขระที่จะต้องลบออกในวงเล็บเหลี่ยมในช่วงเวลาของการเปลี่ยน โค้ดตัวอย่างจะเป็นดังต่อไปนี้:

String s = "$116.42".replaceAll("[$]", "");

-3

คุณสามารถใช้str = str.replace("X", "");ตามที่กล่าวไว้ก่อนหน้านี้และคุณจะสบายดี สำหรับข้อมูลของคุณ''ไม่ใช่ตัวอักษร (หรือตัวอักษร) ที่ว่างเปล่า แต่'\0'เป็น

ดังนั้นคุณสามารถใช้str = str.replace('X', '\0');แทน


9
สิ่งนี้ไม่ถูกต้อง '\ 0' จะสร้างอักขระเป็นโมฆะจริง str.replace ('X', '\ 0') เทียบเท่ากับ str.replace ("X", "\ u0000") ซึ่งไม่ได้เป็นอย่างที่ OP ต้องการ
Andrey
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.