Как получить числа из строки?

Я использую Java StreamTokenizer для извлечения различных слов и чисел из строки, но столкнулся с проблемой, когда речь идет о числах, содержащих запятые, например. 10 567 читается как 10,0 и ,567.

Мне также нужно удалить все нечисловые символы из чисел, где они могут встречаться, например. 678,00 долларов должно быть 678,00 или -87 должно быть 87.

Я считаю, что этого можно достичь с помощью методов whiteSpace и wordChars, но кто-нибудь знает, как это сделать?

Основной код streamTokenizer в настоящее время:

        BufferedReader br = new BufferedReader(new StringReader(text));
        StreamTokenizer st = new StreamTokenizer(br);
        st.parseNumbers();
        st.wordChars(44, 46); // ASCII comma, - , dot.
        st.wordChars(48, 57); // ASCII 0 - 9.
        st.wordChars(65, 90); // ASCII upper case A - Z.
        st.wordChars(97, 122); // ASCII lower case a - z.
        while (st.nextToken() != StreamTokenizer.TT_EOF) {
            if (st.ttype == StreamTokenizer.TT_WORD) {                    
                System.out.println("String: " + st.sval);
            }
            else if (st.ttype == StreamTokenizer.TT_NUMBER) {
                System.out.println("Number: " + st.nval);
            }
        }
        br.close(); 

Или может кто-нибудь предложить REGEXP для достижения этой цели? Я не уверен, полезен ли здесь REGEXP, учитывая, что любой парсинг будет иметь место после того, как токены будут прочитаны из строки.

Спасибо

Мистер Морган.


person Mr Morgan    schedule 17.07.2010    source источник
comment
Что должно произойти с 1,2,3,4?   -  person polygenelubricants    schedule 17.07.2010


Ответы (5)


StreamTokenizer устарел, лучше использовать Scanner, это пример кода для вашей проблемы:

    String s = "$23.24 word -123";
    Scanner fi = new Scanner(s);
    //anything other than alphanumberic characters, 
    //comma, dot or negative sign is skipped
    fi.useDelimiter("[^\\p{Alnum},\\.-]"); 
    while (true) {
        if (fi.hasNextInt())
            System.out.println("Int: " + fi.nextInt());
        else if (fi.hasNextDouble())
            System.out.println("Double: " + fi.nextDouble());
        else if (fi.hasNext())
            System.out.println("word: " + fi.next());
        else
            break;
    }

Если вы хотите использовать запятую в качестве разделителя с плавающей запятой, используйте fi.useLocale(Locale.FRANCE);

person Denis Tulskiy    schedule 17.07.2010
comment
Это очень полезно. И я уже добавил к нему несколько других персонажей. Большое спасибо. - person Mr Morgan; 17.07.2010

Попробуй это:

String sanitizedText = text.replaceAll("[^\\w\\s\\.]", "");

SanitizedText будет содержать только буквы, цифры и пробелы; токенизировать его после этого должно быть легко.

ИЗМЕНИТЬ

Отредактировано, чтобы сохранить десятичную точку (в конце скобки). . является «специальным» для регулярного выражения, поэтому для него требуется экранирование обратной косой черты.

person Carl Smotricz    schedule 17.07.2010
comment
Спасибо. Кажется, работает, но с числом 345,67 фунтов стерлингов он возвращает 34567,00. - person Mr Morgan; 17.07.2010
comment
Легко. Просто добавьте в скобки любые другие символы, которые вы хотите сохранить. Я исправлю это для вас... - person Carl Smotricz; 17.07.2010
comment
Это могло бы решить серьезную проблему. И после того, как этот синтаксический анализ завершен, я могу просто вызвать StreamTokenizer, как указано выше. Спасибо. - person Mr Morgan; 17.07.2010
comment
Однако я замечаю, что двуствольные имена изменены, например. Albany-Caxton становится AlbanyCaxton. Можно ли это предотвратить? - person Mr Morgan; 17.07.2010
comment
Конечно, если вы добавите «-» в конце скобки. Однако, если вы это сделаете, вы можете столкнуться с отрицательными числами. Но тогда вы можете исправить их с помощью простого теста if. - person Carl Smotricz; 17.07.2010
comment
У меня - работает и могу проверить на отрицательные числа. А как насчет апострофа в имени О'Финнеган? - person Mr Morgan; 17.07.2010
comment
Это неправильное решение. Он не будет правильно обрабатывать десятичные дроби или разделители 1000 в валюте. Сканер, как предложил @tulskiy, является правильным и простым решением, встроенным в библиотеку JavaSE. - person Alain O'Dea; 17.07.2010
comment
Я снимаю шляпу перед @tulskiy, его решение гораздо проще локализовать, чем мое. Я даю ему голос за его лучшее решение. - person Carl Smotricz; 17.07.2010

Это сработало для меня:

String onlyNumericText = text.replaceAll("\\\D", "");
person mordekhai    schedule 20.12.2012
comment
После редактирования влезло слишком много \\. Должно быть \\D. - person Michael Chatiskatzi; 27.02.2021

Конечно, это можно сделать с помощью регулярного выражения:

s/[^\d\.]//g

Однако обратите внимание, что он съедает все запятые, что, вероятно, вам нужно, если вы используете американский числовой формат, где запятая разделяет только тысячи. В некоторых языках вместо точки в качестве десятичного разделителя используется запятая. Так что будьте осторожны при разборе международных данных.

Я оставляю это на вас, чтобы перевести это на Java.

person gorn    schedule 17.07.2010
comment
Вот почему я хочу оставить запятые на месте. - person Mr Morgan; 17.07.2010
comment
Я думал, вам нужно число, а не его строковое представление. неважно - person gorn; 18.07.2010

Код для получения чисел из строки. Например, у меня есть строка «123», тогда я хочу номер 123.

    int getNumber(String str){
            int i=0;
            int num=0;
            int zeroAscii = (int)'0';
            while (i<str.length()) {
                int charAscii=(int)str.charAt(i);
                num=num*10+(charAscii-zeroAscii);
                 i++;
                  }   
            return num;
        }

Источник: Как получить число из строки

person Anuj Dhiman    schedule 26.11.2015