文字列から数値を抽出して整数の配列を取得するにはどうすればよいですか?


109

文字列変数(基本的には番号が指定されていない英語の文)があり、すべての数値を整数の配列に抽出したいと思います。正規表現を使用した簡単な解決策があるかどうか疑問に思っていましたか?


私はショーンのソリューションを使用して、少し変更しました:

LinkedList<String> numbers = new LinkedList<String>();

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(line); 
while (m.find()) {
   numbers.add(m.group());
}

1
数字はスペースやその他の文字で囲まれていますか?数値はどのようにフォーマットされていますか?16進数、8進数、2進数、10進数ですか?
ブハケシンディ

私はそれが質問から明らかであると思いました:それは数字のある英文です。さらに、整数配列について話していたので、私が探していたのは整数でした。
John Manak、2010年

回答:


175
Pattern p = Pattern.compile("-?\\d+");
Matcher m = p.matcher("There are more than -2 and less than 12 numbers here");
while (m.find()) {
  System.out.println(m.group());
}

...プリント-212


-?先頭の負の符号に一致します-オプションで。\ dが数字と一致し、我々は記述する必要がある\として、\\しかしJavaのStringインチ したがって、\ d +は1桁以上に一致します。


4
正規表現を説明して、回答を補足してください。
OscarRyz 2010年

3
-?先頭の負の符号に一致します-オプションで。\ dは数字と一致しますが、Java文字列では\を\\として記述する必要があります。したがって、\\ d +はさらにもう1桁一致します
Sean Owen

7
式をPattern.compile( "-?[\\ d \\。] +")に変更して、フロートをサポートしました。あなたは間違いなく私を道に導きます、Thx!
jlengrand

この方法では、数字は検出されますが、フォーマットされた数値は検出されません2,000。そのような使用のため-?\\d+,?\\d+|-?\\d+
Mugoma J. Okomba 2016年

これは単一のカンマのみをサポートするため、「2,000,000」はありません。「2,00」のような文字列も受け入れます。カンマ区切りをサポートする必要がある場合は、:-?\\d+(,\\d{3})*が機能するはずです。
Sean Owen

52

replaceAlljava.lang.Stringメソッドをどのように使用するか:

    String str = "qwerty-1qwerty-2 455 f0gfg 4";      
    str = str.replaceAll("[^-?0-9]+", " "); 
    System.out.println(Arrays.asList(str.trim().split(" ")));

出力:

[-1, -2, 455, 0, 4]

説明

[^-?0-9]+
  • [そして]、単一の任意の順序で、すなわち、一度だけ一致する文字のセットをdelimites
  • ^セットの先頭に使用される特別な識別子。セットに存在するすべての文字ではなく、区切られたセットに存在しないすべての文字に一致することを示すために使用されます。
  • + 1回から無制限の回数まで、可能な限り何度でも、必要に応じて返金
  • -? 「-」と「?」のいずれかの文字
  • 0-9 「0」から「9」までの範囲の文字

4
なぜ疑問符を付けたいのですか?また、これは、お菓子-のようなものと一緒に数、それ自体で9----6そして、1-2-3
Alan Moore

1
ライブラリのインポートを使用しない非常に素晴らしい代替手段;)
Jcc.Sanabria 2017

18
Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher(myString);
while (m.find()) {
    int n = Integer.parseInt(m.group());
    // append n to list
}
// convert list to array, etc

実際には[0-9]を\ dに置き換えることができますが、これには二重のバックスラッシュエスケープが含まれるため、読みにくくなります。


おっと。Sean'sは負の数を処理するため、改善されています。
2010年

2
「-?[0-9] +」を使用すると、負数も処理されます
cegprakash

9
  StringBuffer sBuffer = new StringBuffer();
  Pattern p = Pattern.compile("[0-9]+.[0-9]*|[0-9]*.[0-9]+|[0-9]+");
  Matcher m = p.matcher(str);
  while (m.find()) {
    sBuffer.append(m.group());
  }
  return sBuffer.toString();

これは、小数を保持する数値を抽出するためのものです


ネガを処理しない
OneCricketeer 2018年

5

受け入れられた回答は数字を検出しますが、2,000などのフォーマットされた数値や、4.8などの小数は検出しません。そのような使用のため-?\\d+(,\\d+)*?\\.?\\d+?

        Pattern p = Pattern.compile("-?\\d+(,\\d+)*?\\.?\\d+?");
        List<String> numbers = new ArrayList<String>();
        Matcher m = p.matcher("Government has distributed 4.8 million textbooks to 2,000 schools");
        while (m.find()) {  
            numbers.add(m.group());
        }   
        System.out.println(numbers);

出力: [4.8, 2,000]


1
@JulienS .:同意しない。この正規表現は、OPが要求するよりもはるかに多くのことを行い、誤って実行します。(少なくとも、小数部分はオプションのグループである必要があり、その中のすべてが必要で貪欲です:(?:\.\d+)?
Alan Moore

あなたは確かに小数部分についてそこにポイントを持っています。ただし、フォーマットされた数値に遭遇することは非常に一般的です。
ジュリアン

@AlanMoore SOへの多くの訪問者は、類似性/差異が異なる問題を解決するためのさまざまな方法を探しており、提案が提示されると役立ちます。OPも単純化しすぎている可能性があります。
Mugoma J. Okomba 16

4

有理数の場合、これを使用します。 (([0-9]+.[0-9]*)|([0-9]*.[0-9]+)|([0-9]+))


1
OPは整数ではなく実数を言った。また、ドットをエスケープするのを忘れたため、これらの括弧は不要です。
アランムーア

3

Java 8を使用すると、次のことができます。

String str = "There 0 are 1 some -2-34 -numbers 567 here 890 .";
int[] ints = Arrays.stream(str.replaceAll("-", " -").split("[^-\\d]+"))
                 .filter(s -> !s.matches("-?"))
                 .mapToInt(Integer::parseInt).toArray();
System.out.println(Arrays.toString(ints)); // prints [0, 1, -2, -34, 567, 890]

負の数がない場合は、を取り除くreplaceAll(そしてで使用!s.isEmpty()するfilter2-34ことができます。これは、次のようなものを適切に分割するためだけです(これはsplit、純粋に正規表現で処理することもできますが、かなり複雑です)。

Arrays.stream私たちをオンString[]Stream<String>

filter先頭と末尾の空の文字列、および-数値の一部ではない文字列を削除します。

mapToInt(Integer::parseInt).toArray()通話parseIntごとにString私たちに与えますint[]


または、Java 9にはMatcher.resultsメソッドがあります。これにより、次のようなことが可能になります。

Pattern p = Pattern.compile("-?\\d+");
Matcher m = p.matcher("There 0 are 1 some -2-34 -numbers 567 here 890 .");
int[] ints = m.results().map(MatchResults::group).mapToInt(Integer::parseInt).toArray();
System.out.println(Arrays.toString(ints)); // prints [0, 1, -2, -34, 567, 890]

現状では、これらのどちらも、他の回答に示されているようにPattern/で結果をループするだけの大きな改善Matcherではありませんが、これを使用して大幅に簡略化されたより複雑な操作でこれを追跡したい場合は、より単純なはずです。ストリーム。


1

これを使用してすべての実数を抽出します。

public static ArrayList<Double> extractNumbersInOrder(String str){

    str+='a';
    double[] returnArray = new double[]{};

    ArrayList<Double> list = new ArrayList<Double>();
    String singleNum="";
    Boolean numStarted;
    for(char c:str.toCharArray()){

        if(isNumber(c)){
            singleNum+=c;

        } else {
            if(!singleNum.equals("")){  //number ended
                list.add(Double.valueOf(singleNum));
                System.out.println(singleNum);
                singleNum="";
            }
        }
    }

    return list;
}


public static boolean isNumber(char c){
    if(Character.isDigit(c)||c=='-'||c=='+'||c=='.'){
        return true;
    } else {
        return false;
    }
}

1

実数を表すための分数およびグループ化文字は、言語間で異なる場合があります。同じ実数は、言語によって非常に異なる方法で記述できます。

ドイツ語で200万の数

2,000,000.00

そして英語で

2.000.000,00

特定の文字列から言語にとらわれない方法で実数を完全に抽出する方法:

public List<BigDecimal> extractDecimals(final String s, final char fraction, final char grouping) {
    List<BigDecimal> decimals = new ArrayList<BigDecimal>();
    //Remove grouping character for easier regexp extraction
    StringBuilder noGrouping = new StringBuilder();
    int i = 0;
    while(i >= 0 && i < s.length()) {
        char c = s.charAt(i);
        if(c == grouping) {
            int prev = i-1, next = i+1;
            boolean isValidGroupingChar =
                    prev >= 0 && Character.isDigit(s.charAt(prev)) &&
                    next < s.length() && Character.isDigit(s.charAt(next));                 
            if(!isValidGroupingChar)
                noGrouping.append(c);
            i++;
        } else {
            noGrouping.append(c);
            i++;
        }
    }
    //the '.' character has to be escaped in regular expressions
    String fractionRegex = fraction == POINT ? "\\." : String.valueOf(fraction);
    Pattern p = Pattern.compile("-?(\\d+" + fractionRegex + "\\d+|\\d+)");
    Matcher m = p.matcher(noGrouping);
    while (m.find()) {
        String match = m.group().replace(COMMA, POINT);
        decimals.add(new BigDecimal(match));
    }
    return decimals;
}

1

bar1やaa1bbなどの単語に含まれる数値を除外する場合は、単語境界\ bを任意の正規表現ベースの回答に追加します。例えば:

Pattern p = Pattern.compile("\\b-?\\d+\\b");
Matcher m = p.matcher("9There 9are more9 th9an -2 and less than 12 numbers here9");
while (m.find()) {
  System.out.println(m.group());
}

表示:

2
12

1

文字列から数値を抽出するには、ASCII値を確認することをお勧めします。入力文字列がmyname12345であるとします。数値12345だけを抽出したい場合は、最初に文字列を文字配列に変換してから、次の擬似コードを使用します。

    for(int i=0; i < CharacterArray.length; i++)
    {
        if( a[i] >=48 && a[i] <= 58)
            System.out.print(a[i]);
    }

数値が抽出されたら、配列に追加します

お役に立てれば


Java文字列は、Unicode / UTF-16コード単位のシーケンスをカウントしたものです。UTF-16の設計により、最初の128文字はASCIIエンコーディングと同じ値(同じサイズではない)になります。それ以上に、ASCIIを扱っていると考えるとエラーが発生します。
Tom Blodget、2014年


-1
public static String extractNumberFromString(String number) {
    String num = number.replaceAll("[^0-9]+", " ");
    return num.replaceAll(" ", "");
}

文字列から数値のみを抽出します

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.