2

先行ゼロを無視して、長い文字列から存在する場合は最初の10桁を抽出することに興味があります。さらに、ゼロしかない場合は1つのゼロのみを返し、数値がない場合は空の文字列を返します。一つに合わせたいfindです。

例えば:

  • "abcd00111.g2012asd"に一致する必要があります"1112012"
  • "aktr0011122222222222ddd"に一致する必要があります"1112222222"
  • "asdas000000asdasds0000"に一致する必要があります"0"
  • "adsads.cxzv.;asdasd"に一致する必要があります""

これが私がこれまでに試したことです:IdeoneDemo-コード

Pattern p = Pattern.compile("[1-9]{1}+[0-9]{9}");
Matcher m = p.matcher(str);
if (m.find()) {
  String match = m.group();
  System.out.println(match);
}

問題は、この正規表現には最初の非ゼロの後に9桁の連続した数字が必要であり、任意の9桁(間にある可能性のある非数字文字)が必要なことです。

単一の実行で一致を見つけたいので、if (m.find())代わりに私が持っているコードに注意してください。while (m.find())

アップデート

コメントに基づいて、正規表現では1回の実行では実行できないことを理解しました。

答えは正規表現ベースである必要はありませんが、このメソッドを何度も実行するので最も効率的です。

4

2 に答える 2

6

一般的に、単一のでそれを行うことはできませんfind。連続する数字のシーケンスの最大数がわかっている場合はそれを行うことができますが、それがわからない場合は、少なくともJavaPatternクラスのサポートレベルでは不可能です。私はこれについて間違っていました。Kobiのコメントは、単一の正規表現でそれが可能であることを示しています。ここでコメントを再現します:

ああ、それは正規表現で可能です。10桁の数字をそれぞれキャプチャすることで、次のようになります^[\D0]*(\d)\D*(?:(\d)\D*(?:(\d)\D*(?:(\d)\D*(?#{6 more times}))?)?)?。しかし、それは本当に醜く、うまくスケーリングしません。

ただし、グループを連結する必要があります。最初の正規表現のロジックは非常に優れています。貪欲なプロパティにより、先頭にゼロがある場合は最初のゼロ以外の数字を検索し、ゼロ以外の数字がない場合は最後の0を取得します。 -ゼロ桁。


効率についての話を戸外に投げ出し、短いコードが必要な場合:

String digitOnly = str.replaceAll("\\D+", "");
String noLeadingZero = digitOnly.replaceFirst("^0+", "");
String result = digitOnly.isEmpty() ? "" :
                noLeadingZero.isEmpty() ? "0" : 
                noLeadingZero.substring(0, Math.min(noLeadingZero.length(), 10));

率直に言って、文字列をループするのはaStringBuilderで十分であり、正規表現ソリューションよりも高速である必要があります。

StringBuilder output = new StringBuilder();
boolean hasDigit = false;
boolean leadingZero = true;
for (int i = 0; i < str.length() && output.length() < 10; i++) {
    char currChar = str.charAt(i);
    if ('0' <= currChar && currChar <= '9') {
        hasDigit = true;
        if (currChar != '0') {
            output.append(currChar);
            leadingZero = false;
        } else if (!leadingZero) { // currChar == 0
            output.append(currChar);
        } // Ignore leading zero
    }
}

String result = !hasDigit ? "" :
                output.length() == 0 ? "0" :
                output.toString();

パフォーマンステストコード。適切な近似値が得られるように、実際の入力に似るようにパラメーターを調整する必要があることに注意してください。ループメソッドが正規表現を含むものよりも遅いとは思えません。ただし、違いは大規模な場合にのみ重要です。

于 2013-02-27T06:51:55.087 に答える
2
String test = "sdfsd0000234.432004gr23.022";
StringBuilder sb = new StringBuilder();
for(int i=0;i<test.length();i++) {
    if(Character.isDigit(test.charAt(i))) 
        sb = sb.append(test.charAt(i));
}
String result = sb.toString();
result = result.replaceFirst("^0*", "");  //Remove leading zeros
System.out.println(result);               //Will print 23443200423022
于 2013-02-27T06:55:32.173 に答える