文字列から出現するすべての文字を削除


311

私はこれを使うことができます:

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

XJavaの文字列からすべての文字を削除する方法はありますか?

私はこれを試しましたが、私が望むものではありません: str.replace('X',' '); //replace with space


3
単一の文字列を置き換えてみましたか?
peter.murray.rust 2011年

回答:


523

次の引数ではなく、引数を取るオーバーロードをCharSequence使用してみてください(例:)。Stringchar

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

2
最初の引数は正規表現です。特に、この文字列がユーザー入力からのものである場合は、期待どおりに機能しないことがあります。
vbezhenar 2012

9
@vsb:真実ではありません。その特定のオーバーロードの両方の引数はCharSequenceです。docs.oracle.com/javase/7/docs/api/java/lang/...
LukeH

Xchar型の場合はどうしますか?
KNU 2014年

7
@Kunal:toString最初にそれをする必要があると思います。したがって、コードは次のようになりますstr = str.replace(yourChar.toString(), "");
LukeH 2014年

Unicodeエスケープを使用できることに注意してください。たとえば、str = str.replace("\uffff", "");
非文字を

42

使用する

public String replaceAll(String regex, String replacement)

動作します。

使用法になりますstr.replace("X", "");

実行中

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

戻り値:

lakjsdf xx

6
正規表現は、Java 1.4のサポートに限定されていない限り、おそらくこれでやり過ぎです。バージョン1.5以降replace、単純なをとるオーバーロードがありますCharSequence
LukeH、2011年

3
@LukeH、これはString.replaceへの逆コンパイルされたソースです。正規表現を使用しています。それは正規表現が重く感じられることに同意しますが、それは上記の受け入れられた答えに対してさえも裏で行われていることです。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;

これは、文字列から文字を削除した例です。


4
これは、特に受け入れられた回答と比較すると、非常に非効率的です。
エリックロバートソン

3
私はこの答えはうまくいくと思いますが、正しい答えは短くて速くなります
evilReiko

2

この機会にRegExを使用するのが好きです。

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

ここで、gはグローバルを意味するため、文字列全体を調べ、すべてのXを ''に置き換えます。Xとxの両方を置き換える場合は、次のように言うだけです。

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

(ここで私のフィドルを参照してください:フィドル


これはうまくいくと思いますが、正解はより速く、より短く実行されます。RegExは他の方法よりも遅いことがわかっているため、常にできるだけ多くの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

replaceの代わりにreplaceAllを使用します

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

これはあなたに望ましい答えを与えるはずです。


置換は、replaceAllを使用して終了します。実装を調べます。これは、String#が実装されている置き換える方法です: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」
カプラン

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()、文字を削除するときに、結果の文字列が–とは異なり–開始文字列よりも大きくなることはないことを考慮に入れています。そのため、文字どおりにStringBuilderasに追加しながら、割り当てとコピーが繰り返されるのを回避replace()します。
無意味なの世代は言うまでもありませんPatternし、Matcher内のインスタンスreplace()を除去するために必要なことはありませんことを。このソリューションとは
異なりreplace()、一度に複数の文字を削除できます。


Lambdas / Functional Programmingは現在非常に流行していますが、それを使用して、選択された回答よりも10倍長いソリューションを作成することは、私見では正当化できません。
Volksman

str.replace("…", "")インスタンス化private Pattern(…)してから、生成されたパターンを呼び出しますpublic String replaceAll(String repl)。したがって、次の関数呼び出しが発生しましたreturn Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString())); 。– Sal_Vader_808コメントを参照してください。全体として、私の腰のラムダソリューションよりも約3倍長くなっています。そして、ここで、なぜ私のヒップのラムダソリューションもより高速なのかがうまく説明されています。なぜJavaのString :: replace()がとても遅いのですか?
カプラン

それ自体:ソリューションのサイズについてである場合、他の2倍のソリューションや、外部ライブラリを必要とするソリューションは、批判の候補としてより適切です。Javaの8は本当にないので、年のための言語の一部となっている言語拡張ヒップ。スコアリングシステムの一般的な問題は、時間係数がソリューションの品質よりも重くなることです。その結果、より最新の、時にはより良い解決策がバックサードでますます見つかります。
Kaplan

実行速度ではなくコードの観点から10倍長いことを言及していました。呼び出されるたびに正規表現パターンをコンパイルするものはすべて、かなり遅くなる可能性があります。このような正規表現を頻繁に使用する場合は、コンパイルされたマッチャーをキャッシュして再利用する必要があります(OPは、どのシナリオを使用するかを示していません-フォーム送信からデータをクリーンアップするまれなシナリオであるか、タイトに使用される可能性がありますループは1秒あたり数千回呼び出されます)。
フォルクスマン

パフォーマンスの問題に関しては、提供されたさまざまな回答に対して簡単なベンチマークを実行する新しい回答を追加しました。OPがこの操作を頻繁に実行している場合、内部で正規表現パターンを繰り返し再コンパイルすると非常にコストがかかるため、String.replace()オプションを回避する必要があります。
フォルクスマン

0

現在選択されている回答が内部でコストのかかる正規表現操作を行うという懸念を確認するパフォーマンスベンチマークによる主な回答の評価

これまでに提供された回答は3つの主要なスタイルで提供されます(JavaScriptの回答を無視します;)):

  • String.replace(charsToDelete、 "");を使用します。フードの下で正規表現を使用しています
  • ラムダを使用
  • 単純なJava実装を使用する

コードサイズの面では、明らかにString.replaceが最も簡潔です。単純なJava実装は、Lambdaよりも少し小さくてきれい(IMHO)です(誤解しないでください。適切な場所でLambdaを頻繁に使用しています)。

実行速度は、単純なJava実装、Lambda、次にString.replace()(正規表現を呼び出す)の順でした。

これまでで最も高速な実装は、StringBuilderバッファーを可能な最大結果長に事前割り当てし、「削除する文字」文字列にない文字をバッファーに追加するように調整された単純なJava実装でした。これにより、長さが16文字を超える文字列(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

(カプランの回答からコピーされた)Lambdaの実装は、削除される文字の右側にあるすべての文字の「1つ左へのシフト」を実行するため、遅くなる可能性があります。これは明らかに、削除が必要な多くの文字を含む長い文字列の場合はさらに悪化します。また、Lambda実装自体にオーバーヘッドが発生する場合があります。

String.replace実装は、正規表現を使用し、呼び出しごとに正規表現の「コンパイル」を行います。これを最適化するには、正規表現を直接使用し、コンパイルされたパターンをキャッシュして、毎回コンパイルするコストを回避します。

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()は正しく実装されていません。1つの文字列 "XYZ"が置き換えられ、必要な 'X'、 'Y'、および 'Z'は置き換えられません fromString.replace("X", "").replace("Y", "").replace("Z", "");。これで正しいタイミングが得られます。単純な開始時間:759 | ラムダ時間の開始:1092 | deleteCharsLambda()の開始時間:1420 | 交換の開始時刻を修正:4636
Kaplan

「誰もラムダ関数をメンバー関数にラップしない」-他の実装が呼び出される方法と一致するようにベンチマークシナリオでそれを呼び出す目的を除いて。
Volksman

OPが単一の文字のすべての出現を削除することについて尋ねたことに気づきましたが、あなたの答えは一連の文字を処理するための範囲を変更しました。私が使用した「受け入れられた」回答の実装は、複数の文字に対応することを意図しておらず、意図もしていません。そこで、上記のベンチマークを更新して、これとベンチマーク時間を反映させました。ところで、複数の文字の呼び出しを複数回サポートするようにスコープを拡大したい場合は、コストがかかります。replaceAll( "[XYZ]"、 "")への単一の呼び出しに切り替える方がよい
Volksman '21

ソリューションに示されている関数は、呼び出されたときに1回だけ初期化されます。関数の呼び出しに加えて関数の定義をメンバー関数にラップすることは、ベンチマークをゆがめる唯一の効果があります。
カプラン

各呼び出しの分散が非常に大きいため、単一の呼び出しを行うことによってクイック期間メソッドを適切にベンチマークすることは事実上不可能です。ベンチマークので、通常と同様の方法には多くの繰り返し呼び出しが関与して、合計時間は...(必要な場合や平均値を計算するために)選択肢の合計時間と比較して評価される
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.