Classificando seqüências de caracteres por números contidos em Java

Classificando seqüências de caracteres por números contidos em Java

1. Introdução

Neste tutorial, veremos como classificarStrings alfanuméricos pelos números que eles contêm. Vamos nos concentrar na remoção de todos os caracteres não numéricos deString antes de classificar váriosStrings  pelos caracteres numéricos que permanecem.

Veremos casos extremos comuns, incluindoStrings vazio e números inválidos.

Por fim, faremos um teste de unidade em nossa solução para garantir que funcione conforme o esperado.

2. Delineando o problema

Antes de começarmos, precisamos descrever o que queremos que nosso código atinja. Para este problema específico, faremos as seguintes suposições:

  1. Nossas strings podem conter apenas números, apenas letras ou uma mistura dos dois.

  2. Os números em nossas strings podem ser inteiros ou duplos.

  3. Quando os números em uma string são separados por letras, devemos remover a letra e condensar os dígitos juntos. Por exemplo,2d3  torna-se23.

  4. Para simplificar, quando um número inválido ou ausente aparecer, devemos tratá-los como 0.

Com isso estabelecido, vamos nos concentrar em nossa solução.

3. Uma solução Regex

Como nosso primeiro passo é pesquisar padrões numéricos em nossa entradaString, , swe pode usar expressões regulares, comumente conhecidas como regex.

A primeira coisa que precisamos é do nosso regex. Queremos conservar todos os números inteiros, bem como os pontos decimais da entradaString. Podemos alcançar nosso objetivo com o seguinte:

String DIGIT_AND_DECIMAL_REGEX = "[^\\d.]"

String digitsOnly = input.replaceAll(DIGIT_AND_DECIMAL_REGEX, "");

Vamos explicar brevemente o que está acontecendo:

  1. ‘[^ ]' - denota um conjunto negado, portanto, direcionando qualquer caractere não especificado pela regex incluída

  2. ‘\d' - corresponde a qualquer caractere de dígito (0 - 9)

  3. ‘.' - corresponde a qualquer “.” personagem

Em seguida, usamosString.replaceAll method para remover quaisquer caracteres não especificados por nosso regex. Ao fazer isso, podemos garantir que os três primeiros pontos de nosso objetivo sejam alcançados.

Em seguida, precisamos adicionar algumas condições para garantir queStrings vazio e inválido retorne 0, enquantoStrings válido retorne umDouble válido:

if("".equals(digitsOnly)) return 0;

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

Isso completa nossa lógica. Tudo o que resta fazer é conectá-lo a um comparador para que possamos classificar convenientementeLists of inputStrings. 

Vamos criar um método eficiente para retornar nosso comparador de qualquer lugar que desejemos:

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

4. Teste, teste, teste

Qual a utilidade do código sem testes para verificar sua funcionalidade? Vamos configurar um teste de unidade rápido para garantir que tudo funcione como planejamos:

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);

Neste teste de unidade, incluímos todos os cenários que planejamos. Números inválidos, inteiros, decimais e números separados por letras, todos incluídos em nossa variáveltestStrings .

5. Conclusão

Neste breve artigo, demonstramos como classificar strings alfanuméricas com base nos números dentro delas - fazendo uso de expressões regulares para fazer o trabalho pesado para nós.

Lidamos com exceções padrão que podem ocorrer ao analisar strings de entrada e testamos os diferentes cenários com testes de unidade.

Como sempre, o códigocan be found over on GitHub.