Home > Mobile >  Java regex to detect, and transform on, both case and type changes
Java regex to detect, and transform on, both case and type changes

Time:12-31

Java 11 here, I'm trying to use regexes to build a method that accepts a String, transforms it, and returns the transformed results.

Specifically, the string must only contain 1 alpha-numeric characters ([a-zA-Z0-9] ). Anytime two consecutive characters/elements either change case or switch from alpha -> numeric (and vice versa), I want to insert a hyphen ("-") between them.

Hence:

INPUT             RESULT
====================================
flimFlam          flim-Flam
fliMflam          fliM-flam
fliM8fLam         fli-M-8-f-Lam
flim$Flam         Illegal! $ not allowed!

My best attempt so far:

public String hyphenate(String input) {

    // validate
    String regex = "[a-zA-Z0-9] ";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(input);
    if (!matcher.matches()) {
        throw new IllegalArgumentException("Illegal!");
    }

    // TODO: how to efficiently iterate down the 'input' string and insert hyphen
    // whenever case changes or 2 consecutive elements switch from alpha -> numeric
    // or numeric -> alpha ?

}

Any ideas as to how to accomplish this hyphenation efficiently?

CodePudding user response:

Using regex lookarounds we can try:

String input = "fliM8fLam";
String output = input.replaceAll("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)|(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[a-z])", "-");
System.out.println(output);  // fli-M-8-f-L-am

CodePudding user response:

  1. You can check for a non-alphanumeric character using [^\\p{Alnum}]. Learn more about patterns from the documentation.
  2. You can get the matching groups using [a-z] (?=[A-Z\d])|[A-Z] [a-z] |\d |[A-Z]. Learn more about this pattern from this demo. You can concatenate the matching groups using a regular loop or the Stream API as shown in the following demo.

Demo:

import java.util.regex.MatchResult;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

class Main {
    public static void main(String[] args) {
        // Test
        String[] arr = {
                "flimFlam",
                "fliMflam",
                "fliM8fLam",
                "flim$Flam"
        };
        for (String s : arr) {
            try {
                System.out.println("Trying to hyphenate "   s);
                System.out.println(hyphenate(s));
            } catch (IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    public static String hyphenate(String input) {
        if (Pattern.compile("[^\\p{Alnum}]").matcher(input).find()) {
            throw new IllegalArgumentException("Illegal!");
        }

        String regex = "[a-z] (?=[A-Z\\d])|[A-Z] [a-z] |\\d |[A-Z]";
        return Pattern.compile(regex)
                .matcher(input)
                .results()
                .map(MatchResult::group)
                .collect(Collectors.joining("-"));
    }
}

Output:

Trying to hyphenate flimFlam
flim-Flam
Trying to hyphenate fliMflam
fli-Mflam
Trying to hyphenate fliM8fLam
fli-M-8-f-Lam
Trying to hyphenate flim$Flam
Illegal!
  • Related