2011-11-25 16 views
43

Estoy tratando de encontrar una forma de dividir una cadena en Java que sigue un patrón de este modo:Cómo dividir una cadena entre letras y dígitos (o entre dígitos y letras)?

String a = "123abc345def"; 

Los resultados de este debe ser el siguiente:

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

Sin embargo, me Estoy completamente perplejo en cuanto a cómo puedo lograr esto. Por favor alguien puede ayudarme? He intentado buscar en línea un problema similar, sin embargo, es muy difícil expresarlo correctamente en una búsqueda.

Tenga en cuenta: El número de letras & números pueden variar (por ejemplo Podría haber una cadena como así '1234a5bcdef')

+0

No he probado nada todavía - no sé ni por dónde empezar con el problema, ya que es la primera vez que me he encontrado algo así. –

+0

Se les pide a los usuarios que agreguen una etiqueta de "tarea" a todas las preguntas relacionadas con los problemas de tarea. – Michael

+0

@ Michael esta no es una pregunta de 'tarea'. Nunca antes me he encontrado con este tipo de problema. –

Respuesta

74

Se podría tratar de dividir en (?<=\D)(?=\d)|(?<=\d)(?=\D), como:

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

Compara las posiciones entre un número y no un número (en cualquier orden).

+3

Solo tenga en cuenta que esta solución amenaza los caracteres, que no son ni dígitos ni letras, como letras, por lo que es posible que desee verificar sus partes. – Mario

+0

@Romain, lo hace: http://ideone.com/XDsKn – Qtax

+0

@TimPietzcker No fui el que menos votó esta pregunta: nunca he visto esto usado en Java y pedí sinceramente que confirmara que funciona en Java . Ahora incluso estoy votando eso. – Romain

3

Utilice dos patrones diferentes: [0-9]* y [a-zA-Z]* y divida dos veces cada uno de ellos.

+0

Gracias por su ayuda en esto. No estoy seguro de entender completamente lo que quieres decir. ¿Podrías explicarme con más detalle o dar un ejemplo básico para que pueda ver a qué te refieres? –

+0

Semánticamente, sería '[0-9] +' y '[a-zA-Z] +' ... Aunque harán lo mismo. – Romain

+0

primero divide la cadena en un patrón de dígitos y obtiene una matriz de cadenas, después de eso divide la cadena en el patrón de letras y obtiene una matriz de números. Concatenar dos matrices obtendrás lo que quieras – mishadoff

1

No usé Java por años, así que solo pseudo código, que debería ayudarlo a comenzar (más rápido para mí que buscar todo :)).

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 
} 
9

¿Qué tal:

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; 
} 
+0

Gracias ... Es mi requisito real ... :) –

8

Puede probar esto:

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

El resultado (allMatches) serán:

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

No es una sintaxis válida de Java. –

+0

Gracias Christoffer, he editado. –

2

Si usted está buscando una solución sin usar Java String functi onality (es decir split, match, etc), entonces la siguiente debería ayudar:

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

Esta solución va a dividir los números y las 'palabras', donde 'palabras' son cadenas que no contienen números. Sin embargo, si desea tener solo "palabras" que contengan letras en inglés, puede modificarlas fácilmente agregando más condiciones (como llamar al método isNumber) según sus requisitos (por ejemplo, puede omitir palabras que contengan letras que no sean en inglés). También tenga en cuenta que el método splitString devuelve ArrayList que luego se puede convertir a String matriz.

+0

Me gusta su código, un comentario: return c> = '0' && c <= '9' es mejor que yo. –

+0

@ LaurensOp'tZandt - buena captura, editado. – sergeyan

1

Estaba haciendo este tipo de cosas para el código de misión crítica. Como cada fracción de segundo cuenta porque necesito procesar 180k entradas en una cantidad de tiempo imperceptible. Así que salté la expresión regular y me dividí por completo y permití el procesamiento en línea de cada elemento (aunque agregarlos a un ArrayList<String> estaría bien). Si usted quiere hacer esta cosa exacta, pero necesita que sea algo así como 20 veces más 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)); 
} 
Cuestiones relacionadas