Сортиране на низове по съдържащи се числа в Java

1. Въведение

В този урок ще разгледаме как да сортирате буквено -цифровите низове по числата, които те съдържат. Ще се съсредоточим върху премахването на всички нецифрени знаци от низа, преди да сортираме множество низове по числовите символи, които остават.

Ще разгледаме често срещани случаи на ръбове, включително празни String и невалидни числа.

Накрая ще тестваме модулно нашето решение, за да се уверим, че работи както се очаква.

2. Очертаване на проблема

Преди да започнем, трябва да опишем какво искаме да постигне нашият код. За този конкретен проблем ще направим следните предположения:

  1. Нашите низове могат да съдържат само цифри, само букви или комбинация от двете.
  2. Числата в нашите низове могат да бъдат цели числа или двойни.
  3. Когато числата в низ са разделени с букви, трябва да премахнем буквата и да уплътним цифрите заедно. Например 2d3 става 23.
  4. За простота, когато се появи невалидно или липсващо число, трябва да ги третираме като 0.

С това установено, нека се забием в нашето решение.

3. Разтвор на Regex

Тъй като първата ни стъпка е да търсим числови модели в нашия входен низ, можем да използваме регулярни изрази, известни като регулярни изрази.

Първото нещо, от което се нуждаем, е нашият регулярен израз. Искаме да запазим всички цели числа, както и десетични точки от входния низ . Можем да постигнем целта си със следното:

String DIGIT_AND_DECIMAL_REGEX = "[^\\d.]" String digitsOnly = input.replaceAll(DIGIT_AND_DECIMAL_REGEX, "");

Нека да обясним накратко какво се случва:

  1. „[^]“ - обозначава отрицателен набор, поради което е насочен към всеки символ, който не е посочен от приложения регекс
  2. '\ d' - съвпада с произволен цифров знак (0 - 9)
  3. „.“ - съответства на всяко „.“ характер

След това използваме метода String.replaceAll , за да премахнем всички символи, които не са посочени от нашия регулярен израз. По този начин можем да гарантираме, че първите три точки от нашата цел могат да бъдат постигнати.

След това трябва да добавим някои условия, за да гарантираме, че празните и невалидни низове връщат 0, докато валидните низове връщат валиден Double :

if("".equals(digitsOnly)) return 0; try { return Double.parseDouble(digitsOnly); } catch (NumberFormatException nfe) { return 0; }

Това завършва нашата логика. Остава само да го включите в компаратор, за да можем удобно да сортираме Списъци на входни низове.

Нека създадем ефективен метод за връщане на нашия компаратор от всяко място, където бихме искали:

public static Comparator createNaturalOrderRegexComparator() { return Comparator.comparingDouble(NaturalOrderComparators::parseStringToNumber); }

4. Тест, тест, тест

Каква полза от кода без тестове за проверка на неговата функционалност? Нека да настроим бърз модулен тест, за да гарантираме, че всичко работи както сме планирали:

List 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 expected = Arrays.asList("d2.3.3d", "a1", "d2.2", "d2.f4", "b3", "c4"); assertEquals(expected, testStrings);

В този модулен тест сме събрали всички сценарии, за които сме планирали. Невалидни числа, цели числа, десетични знаци и числа, разделени с букви, всички включени в нашата променлива testStrings .

5. Заключение

В тази кратка статия демонстрирахме как да сортираме буквено-цифрови низове въз основа на числата в тях - като използваме регулярни изрази, за да свършим упоритата работа вместо нас.

Ние се справихме със стандартни изключения, които могат да възникнат при анализиране на входни низове и тествахме различните сценарии с модулно тестване.

Както винаги, кодът може да бъде намерен в GitHub.