Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parsing/converting task with characters and numbers within

It is necessary to repeat the character, as many times as the number behind it.

They are positive integer numbers.

case #1

input: "abc3leson11"

output: "abccclesonnnnnnnnnnn"

I already finish it in the following way:

    String a = "abbc2kd3ijkl40ggg2H5uu";
    String s = a + "*";
    String numS = "";
    int cnt = 0;
    for (int i = 0; i < s.length(); i++) {
        char ch = s.charAt(i);
        if (Character.isDigit(ch)) {
            numS = numS + ch;
            cnt++;
        } else {
            cnt++;
            try {
                for (int j = 0; j < Integer.parseInt(numS); j++) {
                    System.out.print(s.charAt(i - cnt));
                }
                if (i != s.length() - 1 && !Character.isDigit(s.charAt(i + 1))) {
                    System.out.print(s.charAt(i)); 
                }
            } catch (Exception e) {
                if (i != s.length() - 1 && !Character.isDigit(s.charAt(i + 1))) {
                    System.out.print(s.charAt(i)); 
                }
            }
            cnt = 0;
            numS = "";
        }

    }

But I wonder is there some better solution with less and cleaner code?

like image 558
maria Avatar asked Jul 20 '18 14:07

maria


4 Answers

Could you take a look below? I'm using a library from StringUtils from Apache Common Utils to repeat character:

public class MicsTest {

    public static void main(String[] args) {
        String input = "abc3leson11";
        String output = input;
        Pattern p = Pattern.compile("\\d+");
        Matcher m = p.matcher(input);
        while (m.find()) {
          int number = Integer.valueOf(m.group());
          char repeatedChar = input.charAt(m.start()-1);
          output = output.replaceFirst(m.group(), StringUtils.repeat(repeatedChar, number));
        }
        System.out.println(output);
    }
}

In case you don't want to use StringUtils. You can use the below custom method to achieve the same effect:

    public static String repeat(char c, int times) {
        char[] chars = new char[times];
        Arrays.fill(chars,  c);
        return new String(chars);
    }
like image 168
Nghia Do Avatar answered Oct 16 '22 06:10

Nghia Do


Using java basic string regx should make it more terse as follows:

public class He1 {
    private static final Pattern pattern = Pattern.compile("[a-zA-Z]+(\\d+).*");  
    // match the number between or the last using regx;
    public static void main(String... args) {
        String s = "abc3leson11";
        System.out.println(parse(s));
        s = "abbc2kd3ijkl40ggg2H5uu";
        System.out.println(parse(s));
    }

    private static String parse(String s) {
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            int num = Integer.valueOf(matcher.group(1));
            char prev = s.charAt(s.indexOf(String.valueOf(num)) - 1); 
            // locate the char before the number;
            String repeated = new String(new char[num-1]).replace('\0', prev); 
            // since the prev is not deleted, we have to decrement the repeating number by 1;
            s = s.replaceFirst(String.valueOf(num), repeated);
            matcher = pattern.matcher(s);
        }
        return s;
    }
}

And the output should be:

abccclesonnnnnnnnnnn
abbcckdddijkllllllllllllllllllllllllllllllllllllllllggggHHHHHuu
like image 40
Hearen Avatar answered Oct 16 '22 05:10

Hearen


String g(String a){
  String result = "";
  String[] array = a.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
  //System.out.println(java.util.Arrays.toString(array));
  for(int i=0; i<array.length; i++){
    String part = array[i];
    result += part;
    if(++i == array.length){
      break;
    }
    char charToRepeat = part.charAt(part.length() - 1);
    result += repeat(charToRepeat+"", new Integer(array[i]) - 1);
  }
  return result;
}

// In Java 11 this could be removed and replaced with the builtin `str.repeat(amount)`
String repeat(String str, int amount){
  return new String(new char[amount]).replace("\0", str);
}

Try it online.

Explanation:

The split will split the letters and numbers:
abbc2kd3ijkl40ggg2H5uu would become ["abbc", "2", "kd", "3", "ijkl", "40", "ggg", "2", "H", "5", "uu"]

We then loop over the parts and add any strings as is to the result.

We then increase i by 1 first and if we're done (after the "uu") in the array above, it will break the loop.

If not the increase of i will put us at a number. So it will repeat the last character of the part x amount of times, where x is the number we found minus 1.

like image 36
Kevin Cruijssen Avatar answered Oct 16 '22 06:10

Kevin Cruijssen


Here is another solution:

String str = "abbc2kd3ijkl40ggg2H5uu";
    String[] part = str.split("(?<=\\d)(?=\\D)|(?=\\d)(?<=\\D)");
    String res = "";
    for(int i=0; i < part.length; i++){
        if(i%2 == 0){
            res = res + part[i];
        }else {
            res = res + StringUtils.repeat(part[i-1].charAt(part[i-1].length()-1),Integer.parseInt(part[i])-1);
        }
    }
    System.out.println(res);
like image 1
GolamMazid Sajib Avatar answered Oct 16 '22 06:10

GolamMazid Sajib