Подтвердить что ты не робот

Как разбить строку между буквами и цифрами (или между цифрами и буквами)?

Я пытаюсь выработать способ разделения строки в java, которая следует за шаблоном:

String a = "123abc345def";

Результаты этого должны быть следующими:

x[0] = "123";
x[1] = "abc";
x[2] = "345";
x[3] = "def";

Однако я полностью зациклен на том, как я могу это достичь. Пожалуйста, кто-нибудь может мне помочь? Я попытался найти в Интернете аналогичную проблему, однако очень сложно правильно ее правильно найти в поиске.

Обратите внимание: Количество букв и цифр может меняться (например, может быть строка типа "1234a5bcdef" )

4b9b3361

Ответ 1

Вы можете попытаться разделить на (?<=\D)(?=\d)|(?<=\d)(?=\D), например:

str.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");

Он сопоставляет позиции между числом и не числом (в любом порядке).

  • (?<=\D)(?=\d) - соответствует позиции между не цифрой (\D) и цифрой (\d)
  • (?<=\d)(?=\D) - соответствует позиции между цифрой и не цифрой.

Ответ 2

Как насчет:

private List<String> Parse(String str) {
    List<String> output = new ArrayList<String>();
    Matcher match = Pattern.compile("[0-9]+|[a-z]+|[A-Z]+").matcher(str);
    while (match.find()) {
        output.add(match.group());
    }
    return output;
}

Ответ 3

Вы можете попробовать следующее:

Pattern p = Pattern.compile("[a-z]+|\\d+");
Matcher m = p.matcher("123abc345def");
ArrayList<String> allMatches = new ArrayList<>();
while (m.find()) {
    allMatches.add(m.group());
}

Результат (allMatches) будет:

["123", "abc", "345", "def"]

Ответ 4

Используйте два разных шаблона: [0-9]* и [a-zA-Z]* и дважды разделяйте их по каждому из них.

Ответ 5

Если вы ищете решение без использования функциональности Java String (т.е. split, match и т.д.), то следующее должно помочь:

List<String> splitString(String string) {
        List<String> list = new ArrayList<String>();
        String token = "";
        char curr;
        for (int e = 0; e < string.length() + 1; e++) {
            if (e == 0)
                curr = string.charAt(0);
            else {
                curr = string.charAt(--e);
            }

            if (isNumber(curr)) {
                while (e < string.length() && isNumber(string.charAt(e))) {
                    token += string.charAt(e++);
                }
                list.add(token);
                token = "";
            } else {
                while (e < string.length() && !isNumber(string.charAt(e))) {
                    token += string.charAt(e++);
                }
                list.add(token);
                token = "";
            }

        }

        return list;
    }

boolean isNumber(char c) {
        return c >= '0' && c <= '9';
    }

Это решение будет разделять числа и слова, где "слова" - это строки, которые не содержат чисел. Однако, если вам нравится иметь только "слова", содержащие английские буквы, вы можете легко изменить его, добавив больше условий (например, вызов метода isNumber) в зависимости от ваших требований (например, вы можете пропустить слова, содержащие неанглийские буквы). Также обратите внимание, что метод splitString возвращает ArrayList, который позже может быть преобразован в массив String.

Ответ 6

Не использовал Java целую вечность, поэтому просто какой-то псевдо-код, который должен помочь вам начать (быстрее для меня, чем вскрыть все:)).

 string a = "123abc345def";
 string[] result;
 while(a.Length > 0)
 {
      string part;
      if((part = a.Match(/\d+/)).Length) // match digits
           ;
      else if((part = a.Match(/\a+/)).Length) // match letters
           ;
      else
           break; // something invalid - neither digit nor letter
      result.append(part);
      a = a.SubStr(part.Length - 1); // remove the part we've found
 }

Ответ 7

Я делал такие вещи для критически важного кода. Как и каждая часть секунды, я рассчитываю, что мне нужно обработать 180 тыс. Записей за незаметное количество времени. Таким образом, я пропустил регулярное выражение и полностью разделился и разрешил встроенную обработку каждого элемента (хотя добавление их к ArrayList<String> было бы в порядке). Если вы хотите сделать это точно, но нужно, чтобы это было примерно как 20x быстрее...

void parseGroups(String text) {
    int last = 0;
    int state = 0;
    for (int i = 0, s = text.length(); i < s; i++) {
        switch (text.charAt(i)) {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                if (state == 2) {
                    processElement(text.substring(last, i));
                    last = i;
                }
                state = 1;
                break;
            default:
                if (state == 1) {
                    processElement(text.substring(last, i));
                    last = i;
                }
                state = 2;
                break;
        }
    }
    processElement(text.substring(last));
}

Ответ 8

Разве это не "d+|d+" делать работу вместо громоздкой: "(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)"?