Как распарсить строку, которая имеет дробные числа
Имеется к примеру вот такой текст Это стоит 11 бакс, 5.0 а 110 вот это 1.1 - 12. Нужно целые числа заменить словами. Т.е. итог должен выглядеть таким образом Это стоит одиннадцать бакс, 5.0 а сто десять вот это 1.1 - двенадцать. Не понимаю какую регулярку применить, чтобы двенадцать тоже учитывало, т.к. там конец предложения и получается 12.
Ответы (1 шт):
Регулярное выражение может выглядеть так:
Pattern num = Pattern.compile("(?<!\\.)\\d+(?!\\.\\d+)");
(?<!\\.)- look-behind: чтобы не было десятичной точки перед последовательностью цифр\\d+- последовательность из минимум одной цифры(?!\\.\\d+)- look-ahead: после цифр нет точки, за которой идёт последовательность цифр
Для замены чисел на слова начиная с Java 9 можно применить метод Matcher::replaceAll(Function<MatchResult, String> replacer), позволяющий преобразовать совпадение в регулярке в нужное значение, т.е. в данном случае число в слова.
Например, функция translate для преобразования чисел в диапазоне [0, 999] может быть такой:
static final String[] below20 = {
"ноль", "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять",
"десять", "одиннадцать", "двенадцать", "тринадцать", "четырнадцать",
"пятнадцать", "шестнадцать", "семнадцать", "восемнадцать", "девятнадцать"
};
static final String[] tens = {
"двадцать", "тридцать", "сорок", "пятьдесят", "шестьдесят", "семьдесят", "восемьдесят", "девяносто"
};
static final String[] hunds = {
"сто", "двести", "триста", "четыреста", "пятьсот", "шестьсот", "семьсот", "восемьсот", "девятьсот"
};
static String translate(int i) {
if (i == 0) return below20[0];
StringBuilder sb = new StringBuilder();
if (i >= 100) {
sb.append(hunds[i / 100 - 1]);
}
int p = i % 100;
if (sb.length() > 0 && p > 0) {
sb.append(' ');
}
if (p < 20) {
sb.append(below20[p]);
} else {
sb.append(tens[p/10 - 2]).append(' ').append(below20[p % 10]);
}
return sb.toString();
}
Для упрощения вызова translate как ссылки на метод, можно написать адаптер:
static String translate(MatchResult mr) {
return translate(Integer.parseInt(mr.group()));
}
Тест:
String s = "Это стоит 11 бакс, 5.0 а 110 вот это 1.1 - 12.";
Pattern num = Pattern.compile("(?<!\\.)\\d+(?!\\.\\d+)");
// теcтовый вывод совпадений регулярки
num.matcher(s).results() // Stream<MatchResult>
.map(MatchResult::group) // Stream<String>
.forEach(System.out::println);
String words = num.matcher(s).replaceAll(MyClass::translate);
System.out.println(words);
Результат:
11
110
12
Это стоит одиннадцать бакс, 5.0 а сто десять вот это 1.1 - двенадцать.