Como dividir uma string entre letras e dígitos (ou entre dígitos e letras)?

Eu estou tentando descobrir uma maneira de dividir uma string em java que segue um padrão como:

String a = "123abc345def"; 

Os resultados disso devem ser os seguintes:

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

No entanto, estou completamente perplexo sobre como posso conseguir isso. Por favor alguém pode me ajudar? Eu tentei pesquisar on-line por um problema semelhante, no entanto, é muito difícil colocá-lo corretamente em uma pesquisa.

Por favor, note: O número de letras e números pode variar (por exemplo, pode haver uma string como ‘1234a5bcdef’)

Você poderia tentar dividir em (?<=\D)(?=\d)|(?<=\d)(?=\D) , como:

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

Ele combina posições entre um número e não-um-número (em qualquer ordem).

E se:

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

Você pode tentar isto:

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

O resultado (allMatches) será:

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

Use dois padrões diferentes: [0-9]* e [a-zA-Z]* e divida duas vezes por cada um deles.

Se você está procurando uma solução sem usar a funcionalidade Java String (ou seja, split , match , etc.), o seguinte deve ajudar:

 List splitString(String string) { List list = new ArrayList(); 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'; } 

Essa solução dividirá números e "palavras", em que "palavras" são strings que não contêm números. No entanto, se você quiser ter apenas "palavras" contendo letras em inglês, poderá modificá-las facilmente adicionando mais condições (como a chamada de método isNumber ), dependendo das suas necessidades (por exemplo, você pode pular as palavras que contêm letras não inglesas). Observe também que o método splitString retorna ArrayList que mais tarde pode ser convertido em array String .

Não usei Java por muito tempo, então apenas alguns pseudo-códigos, que devem ajudar você a começar (mais rápido para mim do que procurar por tudo :)).

  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 } 

Eu estava fazendo esse tipo de coisa para o código de missão crítica. Como cada fração de segundo conta, preciso processar 180 mil inputs em uma quantidade de tempo imperceptível. Então eu pulei o regex e dividi completamente e permiti o processamento in-line de cada elemento (embora adicioná-los a um ArrayList seria ótimo). Se você quer fazer exatamente isso, mas precisa ser algo 20x mais rápido …

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