Karakter dizisindeki tüm char oluşumlarını kaldır


311

Bunu kullanabilirsiniz:

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

Tüm karakter oluşumlarını kaldırmanın bir yolu var mı XJava'da bir String'den ?

Bunu denedim ve istediğim şey değil: str.replace('X',' '); //replace with space


3
Tek karakterli Dizeleri değiştirmeyi denediniz mi?
peter.murray.rust

Yanıtlar:


523

Aşağıdakiler yerine bağımsız değişkenler alan aşırı yüküCharSequence kullanmayı deneyin (örn. String) char:

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

2
İlk argüman düzenli ifadedir, bazen özellikle bu dize kullanıcı girdisinden geliyorsa beklendiği gibi çalışmaz.
vbezhenar

9
@vsb: Doğru değil. Bu aşırı yükün her iki argümanı da vardır CharSequence. docs.oracle.com/javase/7/docs/api/java/lang/...
LukeH

XChar türünde ne yapmalı ?
KNU

7
@Kunal: Sanırım toStringönce ihtiyacınız olacak . Yani kodunuz şöyle bir şey olurdustr = str.replace(yourChar.toString(), "");
LukeH

Unicode kaçışlarını kullanabileceğinizi unutmayın, örneğin karakterleri kaldırmayınstr = str.replace("\uffff", "");
Jaime Hablutzel

42

kullanma

public String replaceAll(String regex, String replacement)

çalışacak.

Kullanım olurdu str.replace("X", ""); .

yürütme

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

İadeler:

lakjsdf xx

6
Regex, Java 1.4'ü desteklemenizle sınırlı olmadıkça muhtemelen aşırıya kaçar - 1.5 sürümünden bu yana replacebasit bir aşırı yükleme var CharSequence.
LukeH

3
@LukeH, Bu String.replace için ayrıştırılmış kaynağıdır. Normal ifade kullanıyor. Normal ifadenin ağır hissettiğine katılıyorum, ancak yukarıdaki kabul edilen cevap için bile kaputun altında olan şey bu. public String replace (CharSequence var1, CharSequence var2) {return Pattern.compile (var1.toString (), 16) .matcher (this) .replaceAll (Matcher.quoteReplacement (var2.toString ())); }
Perry Tew


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

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

Bu, karakteri - Dize'den kaldırdığım örnek.


4
Bu, özellikle kabul edilen cevapla karşılaştırıldığında çok verimsizdir.
Erick Robertson

3
Bu cevabın işe yaradığını düşünüyorum, ama doğru cevap daha kısa ve hızlı
evilReiko

2

Bu vesileyle RegEx kullanmayı seviyorum:

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

burada g global anlamına gelir, böylece tüm dizenizden geçecek ve tüm X'in yerine ''; hem X hem de x'i değiştirmek istiyorsanız, şunları söylersiniz:

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

(buradaki kemanımı gör : keman )


Sanırım bu işe yarayabilir, ancak doğru cevap daha hızlı ve daha kısa yürütür,
RegEx'ten

2

Merhaba Aşağıdaki bu kodu deneyin

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 yerine başka bir dizemiz olsaydı bunu nasıl yapardın? Güzel çözüm!
Mona Jalal

2

Değiştirmek için replaceAll kullanın

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

Bu size istenen cevabı vermelidir.


replaceAll kullanarak biter. Uygulamaya bakın. Dize # değiştirme şu şekilde uygulanır: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" veriyor
Kaplan

0

Burada, string olarak iletilen tüm karakterleri kaldıran bir lambda işlevi var

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"

Bu çözüm, replace()karakterleri kaldırırken sonuçta ortaya çıkan Dize'nin - fark olarak - hiçbir zaman başlangıç ​​Dize'den daha büyük olmayacağını dikkate alır. Böylece, karakter olarak olduğu StringBuildergibi karakter-bilge eklerken tekrarlanan tahsis ve kopyalamayı önler replace().
Sökülmek için asla gerekli olan anlamsız nesillerden Patternve Matcherörneklerden bahsetmiyorum bile replace(). Bu çözümden
farkı replace(), bir swoop'ta birkaç karakteri silebilir.


Lambdas / Fonksiyonel Programlama şu anda çok kalça ama seçilen cevaptan 10 kat daha uzun bir çözüm oluşturmak için kullanmak IMHO'yu haklı gösteremez, dolayısıyla aşağı oy.
Volksman

str.replace("…", "")private Pattern(…)oluşturulan desen çağrılarını başlatır public String replaceAll(String repl). Böylece aşağıdaki işlev çağrıları oldu: return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString())); - Sal_Vader_808 yorumuna bakınız. Sonuçta benim kalça lambda çözeltiden 3 kat daha uzun . Ve burada benim kalça lambda çözümünün neden
Kaplan

kendi başına : Eğer çözümün büyüklüğü hakkında olsaydı, iki kat daha büyük başka çözümler veya harici bir kütüphane gerektiren çözümler eleştiri için daha uygun adaylar olurdu. Java 8'den bu yana yıllardır dilin bir parçası olan bir dil uzantısı gerçekten kalça değil . Puanlama sistemi ile ilgili genel bir problem, zaman faktörünün bir çözüm kalitesinden daha ağır olmasıdır. Sonuç olarak, daha güncel ve bazen daha da iyi çözümler giderek üçüncü sırada yer almaktadır.
Kaplan

Ben yürütme hızı değil kod açısından 10 kat daha uzun atıfta. Her çağrıldığında normal ifade düzenini derleyen her şey çok daha yavaş olabilir. Derlenmiş eşleştiriciyi önbelleğe almanız ve böyle bir regex'i yüksek frekansta kullanıyorsanız (OP, hangi senaryo kullanıldığını söylemiyorsa - bir form gönderiminden verileri temizlemek için nadir bir senaryo olabilir veya sıkı bir şekilde kullanılabilirse) döngü saniyede 1000 kez denir).
Volksman

Performans kaygıları ile ilgili olarak, verilen cevaplar üzerinde hızlı bir değerlendirme yapan yeni bir cevap ekledim. OP bu işlemi sık sık yapıyorsa, başlık altındaki normal ifade modelinin tekrar tekrar derlenmesi çok maliyetli olduğundan String.replace () seçeneğinden kaçınmalıdır.
Volksman

0

Ana cevapların, mevcut seçili cevabın kaputun altında pahalı regex operasyonları yaptığına dair endişeleri doğrulayan bir performans ölçütü ile değerlendirilmesi

Bugüne kadar verilen cevaplar 3 ana stilde gelmektedir (JavaScript cevabını yok saymak;)):

  • String.replace (charsToDelete, "") kullanın; başlık altında normal ifade kullanan
  • Lambda kullanın
  • Basit Java uygulamasını kullanın

Kod boyutu açısından açıkça String.replace en kısa olanıdır. Basit Java uygulaması Lambda'dan biraz daha küçük ve daha temiz (IMHO) (beni yanlış anlamayın - Lambdas'ı uygun olan yerlerde sık sık kullanıyorum)

Yürütme hızı, en hızlıdan en yavaşına doğru: basit Java uygulaması, Lambda ve sonra String.replace () (regex'i çağırır) idi.

Şimdiye kadar en hızlı uygulama, StringBuilder arabelleğini olası maksimum sonuç uzunluğuna önceden yerleştirecek ve daha sonra "silinecek karakter" dizesinde olmayan arabelleğe chars ekleyecek şekilde ayarlanmış basit Java uygulamasıydı. Bu, Dizeler> 16 karakter uzunluğunda (StringBuilder için varsayılan ayırma) oluşacak yeniden tahsisleri engeller ve oluşan dizenin bir kopyasından karakterleri silmenin "slayt sola" performans ismini Lambda uygulamasıdır.

Aşağıdaki kod, her bir uygulamayı 1.000.000 kez çalıştıran basit bir karşılaştırma testi gerçekleştirir ve geçen süreyi kaydeder.

Kesin sonuçlar her çalışmaya göre değişir, ancak performans sırası asla değişmez:

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

Lambda uygulaması (Kaplan'ın cevabından kopyalandığı gibi) daha yavaş olabilir, çünkü silinmekte olan karakterin sağındaki tüm karakterlerden "bir sola kaydırma" gerçekleştirir. Bu, silme gerektiren birçok karakter içeren daha uzun dizeler için daha da kötüleşir. Ayrıca Lambda uygulamasının kendisinde bir miktar ek yük olabilir.

String.replace uygulaması, regex kullanır ve her çağrıda bir regex "compile" yapar. Bunun bir optimizasyonu, regex'i doğrudan kullanmak ve her seferinde derleme maliyetini önlemek için derlenen deseni önbelleğe almak olacaktır.

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

Lambda işlevi olması gerektiği gibi çağrılırsa, zamanlama aşağıdaki gibidir (hiç kimse bir lambda işlevini üye işlevine sarmaz) . Ayrıca deleteCharsReplace () yanlış uygulanmıştır: bir 'XYZ' dizesinin yerine geçer ve gerekli olan 'X', 'Y' ve 'Z' yerine geçmez fromString.replace("X", "").replace("Y", "").replace("Z", "");. Şimdi doğru zamanlamayı alıyoruz: Basit başlangıç ​​Zamanı: 759 | Başlangıç ​​lambda Süre: 1092 | Başlat deleteCharsLambda () Süre: 1420 | Başlamayı
Kaplan

"Hiç kimse lambda işlevini üye işlevine sarmaz" - diğer uygulamaların çağrılmasıyla tutarlı olması için bir karşılaştırma senaryosunda çağırmak dışında.
Volksman

OP'nin tek bir karakterin tüm tekrarlarını kaldırmasını istediğini fark ettim, ancak cevabınız bir dizi karakterle başa çıkmak için kapsamı değiştirdi. Kullandığım "kabul edilen" cevap uygulaması, birden fazla karaktere hitap etmemekte ve hiç tasarlanmamıştır. Bu yüzden yukarıdaki ölçütü bu ve kıyaslama sürelerini yansıtacak şekilde güncelledim. BTW kapsamını artırmak istiyorsanız birden çok karakteri arayarak birden fazla kez değiştirmek için pahalıya mal olur. Değiştirmek için tek bir çağrıya geçmek daha iyiAll ("[XYZ]", "")
Volksman

Gösterildiği gibi işlev çözeltisi yalnızca çağrıldığında kez inited edilir. İşlev tanımını işlev çağrısına ek olarak üye işlevine sarmak, karşılaştırmayı bozmak için tek etkiye sahiptir.
Kaplan

Her çağrının varyansı çok yüksek olduğundan, tek bir çağrı yaparak hızlı süre yöntemlerini doğru bir şekilde kıyaslamak neredeyse imkansızdır. Bu yüzden kıyaslama normalde aynı yönteme birçok tekrarlanan çağrıyı içerir ve daha sonra toplam süre alternatiflerin toplam süreleriyle karşılaştırmak için değerlendirilir (veya gerekirse bir ortalama hesaplamak için) ..
Volksman

0

Değiştirme sırasında karakterlerin kaldırılması gereken köşeli parantezlerin içine koymanız gerekir. Örnek kod aşağıdaki gibi olacaktır:

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

-3

Daha str = str.replace("X", "");önce de belirtildiği gibi kullanabilirsiniz ve iyi olacaksınız. Bilginiz için ''boş (veya geçerli) bir karakter değil '\0'.

Bunun str = str.replace('X', '\0');yerine kullanabilirsiniz .


9
bu yanlış. '\ 0' gerçek bir boş karakter üretecektir. str.replace ('X', '\ 0') OP'nin istediği gibi olmayan str.replace ("X", "\ u0000") ile eşdeğerdir
Andrey
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.