0

I would like to extract number from a given string sentence and convert into a numeric value. For example,

Input: "Hello I have two passwords with dk12kdkd and 2kdkae5."

output: "Hello I have two passwords with dkONETWOkdkd and TWOkdkaeFIVE."

I am confused with how to extract numbers and change value to get back original one.

Thanks for the help!

public class Main {

  public static Pattern pattern = Pattern.compile("\\d+");


  public static void main(String[] args) {
    String testString = "Hello I have two passwords with dk12kdkd and 25kdkae5.";
    String singleDigits[] = {"ZERO", "ONE", "TWO", "THREE",
            "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"};


    Matcher matcher = pattern.matcher(str);

    while (matcher.find()) {
        str = str.replace(matcher.group(),
                String.valueOf(Integer.parseInt(matcher.group()));
    } // confused from here.
}
1
  • I added the solution using your approach (Matcher) Commented Jun 1, 2020 at 4:44

3 Answers 3

1

This suggestion matches your approach with matching regex using Matcher and Pattern

Apply a regex to extract the digits, then replace each one with the matching index from the array using replace() method.

Online demo http://tpcg.io/qYIn6e6h

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    static String singleDigits[] = {"ZERO", "ONE", "TWO", "THREE",
            "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"};

    public static void main(String[] args) {

        String regex = "(\\d+)";
        String testString = "Hello I have two passwords with dk12kdkd and 25kdkae5.";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(testString);

        while ( matcher.find() ) {
            testString = testString.replaceFirst(matcher.group(1), getDigitsText(matcher.group(1)) );
        }
        System.out.println( testString);
    }

 /**
 * Gets the text representation of the given number.
 * Example:  Input: 39 outputs: THREENINE
 */
    public static String getDigitsText( String digitText ){
        //split digits if more than one digit. split("") works since Java 8
        String[] digitStrings = digitText.split("");
        //get digit for string
        String text = "";
        for (String digitString : digitStrings){
            //parase string to int
            int digit = Integer.parseInt(digitString);
            //get matching text from 
            text += singleDigits[digit];
        }

        return text;
    }
}

Output:

Hello I have two passwords with dkONETWOkdkd and TWOFIVEkdkaeFIVE.

Approach

  • Used Matcher and Pattern to extract digits from String using regex (\d+)
  • Regex returns every number portion inside that String, it could be multiple digits.
  • This method getDigitsText() will take that String, split it into an array of Strings, each element represents one character that must be a digit.
  • Then iterate the array, getting the name of number from the singleDigits[] array
  • The method concats the name and returns the text representation of the given number.
  • The matcher loop inside main will simply replace the digits String with names String built in the method.
  • Result is printed after loop finishes.
Sign up to request clarification or add additional context in comments.

Comments

1
public class Main {

    public static void main(String[] args) {
        String testString = "Hello I have two passwords with dk12kdkd and 25kdkae5.";
        String singleDigits[] = { "ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE" };
        HashMap<String, String> dict = new HashMap<>();
        for (int i = 0; i < singleDigits.length; i++) {
            dict.put(String.valueOf(i), singleDigits[i]);
        }
        for (char s : testString.toCharArray()) {
            if (dict.containsKey(String.valueOf(s))) 
                testString = testString.replace(String.valueOf(s), dict.get(String.valueOf(s)));
        }
        System.out.println(testString);
    }
}

Output

Hello I have two passwords with dkONETWOkdkd and TWOFIVEkdkaeFIVE.

Comments

0

I don’t think I’d use a regular expression for this. I am offering three avenues:

  1. The easy way: for each digit from 0 through 9, replace every occurrence.
  2. Build the result in a StringBuilder. For each char in the original string append the appropriate word if it’s a digit, otherwise just the char.
  3. A fix to your regex approach.

Replace all digits

I have put your declaration outside the method (you don’t have to do that):

private static final String SINGLE_DIGITS[] = { "ZERO", "ONE", "TWO", "THREE",
        "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE" };

Now we do:

    String testString = "Hello I have two passwords with dk12kdkd and 25kdkae5.";

    for (int d = 0; d < 10; d++) {
        testString = testString.replace(String.valueOf(d), SINGLE_DIGITS[d]);
    }
    System.out.println(testString);

Output:

Hello I have two passwords with dkONETWOkdkd and TWOFIVEkdkaeFIVE.

When some digit is not found (for example, 0), replace() just returns the same string (or an equal one, I don’t care). If on the other hand a digit occurs more than once (both 2 and 5 do), every occurrence is replaced. This is not the most efficient way, but for strings the size of yours you should be fine.

Build result linearly

I am using these further declarations:

private static final BitSet DIGITS = new BitSet();
static {
    DIGITS.set('0', '9' + 1);
}

Now we can do:

    StringBuilder buf = new StringBuilder();
    for (int ix = 0; ix < testString.length(); ix++) {
        char ch = testString.charAt(ix);
        if (DIGITS.get(ch)) {
            buf.append(SINGLE_DIGITS[Character.getNumericValue(ch)]);
        } else {
            buf.append(ch);
        }
    }
    String result = buf.toString();

    System.out.println(result);

Output is the same as before. This is the recommended way if efficiency is a priority.

Your approach with regex

First, since you want 12 replaced by ONETWO(not TWELVE), don’t include a + in your regular expression:

public static Pattern pattern = Pattern.compile("\\d");

Now for each digit found, make a lookup in SINGLE_DIGITS to find the replacement:

    Matcher matcher = pattern.matcher(testString);

    while (matcher.find()) {
        testString = testString.replace(matcher.group(),
                SINGLE_DIGITS[Integer.parseInt(matcher.group())]);
    }

    System.out.println(testString);

The output is the same as before.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.