1. Введение
В этом руководстве мы рассмотрим, как сортировать буквенно -цифровые строки
по содержащимся в них числам. Мы сосредоточимся на удалении всех нечисловых символов из строки
перед сортировкой нескольких строк
по оставшимся числовым символам.
Мы рассмотрим распространенные пограничные случаи, включая пустые String
и недопустимые числа.
Наконец, мы проведем модульное тестирование нашего решения, чтобы убедиться, что оно работает должным образом.
2. Описание проблемы
Прежде чем мы начнем, нам нужно описать, чего мы хотим добиться от нашего кода. Для этой конкретной задачи мы сделаем следующие предположения:
- Наши строки могут содержать только цифры, только буквы или их сочетание.
- Числа в наших строках могут быть целыми или двойными.
- Когда числа в строке разделены буквами, мы должны удалить букву и сжать цифры вместе. Например,
2d3
становится23.
- Для простоты, когда появляется недопустимое или отсутствующее число, мы должны рассматривать их как 0.
Установив это, давайте приступим к нашему решению.
3. Решение для регулярных выражений
Поскольку нашим первым шагом является поиск числовых шаблонов в нашей входной строке,
мы можем использовать регулярные выражения, широко известные как регулярные выражения.
Первое, что нам нужно, это наше регулярное выражение. Мы хотим сохранить все целые числа, а также десятичные точки из входной строки
. Мы можем достичь нашей цели с помощью следующего:
String DIGIT_AND_DECIMAL_REGEX = "[^\\d.]"
String digitsOnly = input.replaceAll(DIGIT_AND_DECIMAL_REGEX, "");
Кратко объясним, что происходит:
'[^ ]'
- обозначает инвертированный набор, поэтому нацелен на любой символ, не указанный в заключенном регулярном выражении.'\d'
– соответствует любому цифровому символу (0 – 9)'.'
– соответствует любому «.» персонаж
Затем мы используем метод String.replaceAll
для удаления любых символов, не указанных в нашем регулярном выражении. Делая это, мы можем гарантировать, что первые три пункта нашей цели могут быть достигнуты.
Затем нам нужно добавить некоторые условия, чтобы гарантировать, что пустые и недопустимые строки
возвращают 0, а действительные строки
возвращают действительное значение Double
:
if("".equals(digitsOnly)) return 0;
try {
return Double.parseDouble(digitsOnly);
} catch (NumberFormatException nfe) {
return 0;
}
Это завершает нашу логику. Все, что осталось сделать, это подключить его к компаратору, чтобы мы могли удобно сортировать списки
входных строк.
Давайте создадим эффективный метод для возврата нашего компаратора из любого места:
public static Comparator<String> createNaturalOrderRegexComparator() {
return Comparator.comparingDouble(NaturalOrderComparators::parseStringToNumber);
}
4. Тест, тест, тест
Что хорошего в коде без тестов для проверки его функциональности? Давайте настроим быстрый модульный тест, чтобы убедиться, что все работает так, как мы планировали:
List<String> testStrings =
Arrays.asList("a1", "d2.2", "b3", "d2.3.3d", "c4", "d2.f4",); // 1, 2.2, 3, 0, 4, 2.4
testStrings.sort(NaturalOrderComparators.createNaturalOrderRegexComparator());
List<String> expected = Arrays.asList("d2.3.3d", "a1", "d2.2", "d2.f4", "b3", "c4");
assertEquals(expected, testStrings);
В этом модульном тесте мы упаковали все запланированные сценарии. Недопустимые числа, целые числа, десятичные дроби и числа, разделенные буквами, включены в нашу переменную testStrings
.
5. Вывод
В этой короткой статье мы продемонстрировали, как сортировать буквенно-цифровые строки на основе чисел внутри них, используя регулярные выражения, которые делают за нас тяжелую работу.
Мы обработали стандартные исключения, которые могут возникнуть при анализе входных строк, и протестировали различные сценарии с помощью модульного тестирования.
Как всегда, код можно найти на GitHub.