web-dev-qa-db-fra.com

Comment diviser String avec un séparateur mais sans supprimer ce séparateur en Java?

Je suis confronté à un problème de division de String.

Je veux diviser un String avec un séparateur mais sans perdre ce séparateur.

Lorsque nous utilisons la méthode somestring.split(String separator) dans Java elle divise le String mais supprime la partie séparatrice de String. Je ne veux pas cela se passer.

Je veux un résultat comme ci-dessous:

String string1="Ram-sita-laxman";
String seperator="-";
string1.split(seperator);

Sortie:

[Ram, sita, laxman]

mais je veux plutôt le résultat comme celui ci-dessous:

[Ram, -sita, -laxman]

Existe-t-il un moyen d'obtenir une sortie comme celle-ci?

65
sag
string1.split("(?=-)");

Cela fonctionne parce que split prend en fait un expression régulière . Ce que vous voyez en fait, c'est un "lookahead positif de largeur nulle".

J'aimerais expliquer plus mais ma fille veut jouer au thé. :)

Modifier: Retour!

Pour expliquer cela, je vais d'abord vous montrer une opération split différente:

"Ram-sita-laxman".split("");

Cela fractionne votre chaîne sur chaque chaîne de longueur nulle. Il y a une chaîne de longueur nulle entre chaque caractère. Par conséquent, le résultat est:

["", "R", "a", "m", "-", "s", "i", "t", "a", "-", "l", "a", "x", "m", "a", "n"]

Maintenant, je modifie mon expression régulière ("") pour ne faire correspondre que les chaînes de longueur nulle si elles sont suivies d'un tiret.

"Ram-sita-laxman".split("(?=-)");
["Ram", "-sita", "-laxman"]

Dans cet exemple, le ?= signifie "lookahead". Plus précisément, cela signifie " positif lookahead". Pourquoi le "positif"? Parce que vous pouvez également avoir négatif lookahead (?!) qui se divisera sur chaque chaîne de longueur nulle qui n'est pas suivie d'un tiret:

"Ram-sita-laxman".split("(?!-)");
["", "R", "a", "m-", "s", "i", "t", "a-", "l", "a", "x", "m", "a", "n"]

Vous pouvez également avoir lookbehind positif (?<=) qui se divisera sur chaque chaîne de longueur nulle précédée d'un tiret:

"Ram-sita-laxman".split("(?<=-)");
["Ram-", "sita-", "laxman"]

Enfin, vous pouvez également avoir lookbehind négatif (?<!) qui se divisera sur chaque chaîne de longueur nulle qui n'est pas précédée d'un tiret:

"Ram-sita-laxman".split("(?<!-)");
["", "R", "a", "m", "-s", "i", "t", "a", "-l", "a", "x", "m", "a", "n"]

Ces quatre expressions sont appelées collectivement les expressions lookaround.

Bonus: les assembler

Je voulais juste montrer un exemple que j'ai rencontré récemment qui combine deux des expressions de contournement. Supposons que vous souhaitiez diviser un identifiant CapitalCase en ses jetons:

"MyAwesomeClass" => ["My", "Awesome", "Class"]

Vous pouvez accomplir cela en utilisant cette expression régulière:

"MyAwesomeClass".split("(?<=[a-z])(?=[A-Z])");

Cela se divise sur chaque chaîne de longueur nulle qui est précédée d'une lettre minuscule ((?<=[a-z])) et suivi d'une lettre majuscule ((?=[A-Z])).

Cette technique fonctionne également avec les identifiants camelCase.

203
Adam Paynter

C'est un peu douteux, mais vous pouvez introduire un séparateur factice en utilisant une fonction de remplacement. Je ne connais pas les méthodes Java, mais en C # cela pourrait être quelque chose comme:

string1.Replace("-", "#-").Split("#");

Bien sûr, vous devez choisir un séparateur factice qui ne se trouve nulle part ailleurs dans la chaîne.

4
Andrew Cooper

Pour ce faire, vous pouvez diviser votre chaîne, puis ajouter votre séparateur au début de chaque chaîne extraite, sauf la première.

2
Dalmas
seperator="-";
String[] splitstrings = string1.split(seperator);
for(int i=1; i<splitstring.length;i++)
{
   splitstring[i] = seperator + splitstring[i];
}

c'est le code qui correspond à la réponse de LadaRaider.

1
mad

Adam a frappé le clou sur la tête! J'ai utilisé sa réponse pour comprendre comment insérer du texte de nom de fichier à partir du navigateur de dialogue de fichier dans une zone de texte riche. Le problème que j'ai rencontré était quand j'ajoutais une nouvelle ligne au "\" dans la chaîne de fichier. La commande string.split se divisait au niveau du\et le supprimait. Après avoir utilisé un mélange de code d'Adam, j'ai pu créer une nouvelle ligne après chaque\dans le nom du fichier.

Voici le code que j'ai utilisé:

OpenFileDialog fd = new OpenFileDialog();
        fd.Multiselect = true;
        fd.ShowDialog();

        foreach (string filename in fd.FileNames)
        {
            string currentfiles = uxFiles.Text;
            string value = "\r\n" + filename;

     //This line allows the Regex command to split after each \ in the filename. 

            string[] lines = Regex.Split(value, @"(?<=\\)");

            foreach (string line in lines)
            {
                uxFiles.Text = uxFiles.Text + line + "\r\n";
            }
        }

Prendre plaisir!

Morse

0
Walrusking