3 votes

Comment diviser une chaîne de caractères pour un chiffre et des lettres en Java ?

Les données d'essai sont par exemple

1a, 12a, 1ab, 12ab, 123a, 123abc

donc si comme entrée nous avons :

String input = "1a";

La sortie sera

String number = "1";
String letter = "a";

Comme vous pouvez le remarquer dans cette chaîne, il y a parfois 1 à 3 chiffres (0-9) et parfois 1 à 3 lettres (A-Z).

Ma première tentative :

J'ai essayé d'utiliser .substring()

Mais cela ne fonctionnera que s'il y a toujours eu, par exemple, le même nombre de chiffres ou de lettres.

Ma deuxième tentative a été :

.split(" ");

Mais cela ne fonctionnera que s'il y a un espace ou tout autre signe entre les deux.

PS. Merci pour la réponse dans les réponses. J'ai vérifié la plupart de vos réponses et elles fonctionnent toutes. La question est maintenant de savoir laquelle est la meilleure ?

1voto

Santosh Thapa Points 61
If your string sequence starts with digits and ends with letters, then the below code will work.

int asciRepresentation, startCharIndex = -1;
    for(int i = 0; i < str.length(); i++) {
        asciRepresentation = (int) str.charAt(i);
        if (asciRepresentation > 47 && asciRepresentation < 58)
            strB.append(str.charAt(i));
        else {
            startCharIndex = i;
            break;
        }
    }
    System.out.println(strB.toString());
    if (startCharIndex != -1)
        System.out.println(str.substring(startCharIndex, str.length()));

1voto

Bentaye Points 3598

Une solution simple sans expressions régulières : Trouvez l'index de la première lettre et divisez la chaîne à cette position.

private String[] splitString(String s) {
  // returns an OptionalInt with the value of the index of the first Letter
  OptionalInt firstLetterIndex = IntStream.range(0, s.length())
    .filter(i -> Character.isLetter(s.charAt(i)))
    .findFirst();

  // Default if there is no letter, only numbers
  String numbers = s;
  String letters = "";
  // if there are letters, split the string at the first letter
  if(firstLetterIndex.isPresent()) {
    numbers = s.substring(0, firstLetterIndex.getAsInt());
    letters = s.substring(firstLetterIndex.getAsInt());
  }

  return new String[] {numbers, letters};
}

Il vous donne :

splitString("123abc") 
returns ["123", "abc"]

splitString("123") 
returns ["123", ""]

splitString("abc") 
returns ["", "abc"]

1voto

Thibaut B. Points 1286

Vous pouvez utiliser une expression rationnelle :

String str = "1a, 12a, 1ab, 12ab, 123a, 123abc";
Pattern p = Pattern.compile("(?<digit>\\d{1,3})(?<letter>[a-z]{1,3})");
Matcher m = p.matcher(str);

while (m.find()){
    System.out.println(m.group("digit")+"/"+m.group("letter"));
}
// Ouput:
// 1/a
// 12/a
// 1/ab...

1voto

Schakal Points 361

Vous trouverez ci-dessous ma proposition. Fonctionne correctement pour les données de test mentionnées

( 1a, 12a, 1ab, 12ab, 123a, 123abc )

Solution :

public ArrayList<String> split(String text) {

Pattern pattern = Pattern.compile("(\\d+)([a-zA-Z]+)");
Matcher matcher = pattern.matcher(text);
ArrayList<String> result = new ArrayList<>();

if (matcher.find() && matcher.groupCount() == 2) {
  result.add(matcher.group(1));
  result.add(matcher.group(2));
}
return result;
}

1voto

Przemysław Moskal Points 2863

Solution :

(regardez aussi la modification que j'ai faite à la fin de ma réponse)

"\\b(\\d{1,3})([a-z]{1,3})(?=,*|\\b)"

Exemple :

String s = "1a, 12a, 1ab, 12ab, 123a, 123abc";
Pattern p = Pattern.compile("\\b(\\d{1,3})([a-z]{1,3})(?=,*|\\b)");
Matcher m = p.matcher(s);
while(m.find()) {
    System.out.println("Group: "+ m.group() + ", letters: " + m.group(1) + ", digits: " + m.group(2));
}

Sortie que vous obtenez :

Group: 1a, letters: 1, digits: a
Group: 12a, letters: 12, digits: a
Group: 1ab, letters: 1, digits: ab
Group: 12ab, letters: 12, digits: ab
Group: 123a, letters: 123, digits: a
Group: 123abc, letters: 123, digits: abc

Explication :

\\b(\\d{1,3})([a-z]{1,3})(?=,*|\\b) toute la regex

\\b - limite des mots

\\d{1,3} - chiffre, de une à trois fois

[a-z]{1,3} - personnages de a à z de une à trois fois

(?=,*|\\b) - c'est une anticipation positive, vous dites qu'après ces lettres vous voulez être présent , ou la limite d'un mot, mais vous ne voulez pas qu'ils soient présents dans le groupe de correspondance (appelé par l'option m.group() )

() - les groupes correspondants sont entre parenthèses - dans ma regex j'ai utilisé deux groupes correspondants : #1 : (\\d{1,3}) #2 : ([a-z]{1,3}) (ils sont imprimés avec m.group(1) y m.group(2) )

Si vous n'êtes pas encore très familier avec la syntaxe des expressions régulières, vous pouvez consulter la documentation de l'API Java de l'élément suivant classe Pattern . Il existe une liste des utilisations possibles des expressions régulières. Cela vaut la peine d'essayer les expressions régulières, car cela pourrait vous faire gagner beaucoup de temps lorsque vous travaillerez avec des chaînes de caractères à l'avenir.


Edit :

En fait, cette regex peut être changée en :

(?<=\\b)(\\d{1,3})([a-z]{1,3})(?=\\b)

Il y a un regard positif derrière (?<=\\b) - cela signifie que vous voulez que les chiffres soient précédés d'une limite de mot (inclure des virgules dans le lookahead et le lookbehind était redondant, je l'ai donc supprimé).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X