web-dev-qa-db-fra.com

Fractionner une chaîne, à chaque nième position

J'utilise cette expression régulière pour diviser une chaîne à chaque 3e position:

String []thisCombo2 = thisCombo.split("(?<=\\G...)");

où les 3 points après le G indiquent chaque nième position à diviser. Dans ce cas, les 3 points indiquent toutes les 3 positions. Un exemple:

Input: String st = "123124125134135145234235245"
Output: 123 124 125 134 135 145 234 235 245.

Ma question est, comment puis-je laisser l'utilisateur contrôler le nombre de positions où la chaîne doit être divisée? En d'autres termes, comment puis-je créer ces 3 points, n points contrôlés par l'utilisateur?

29
Emile Beukes

Pour une grande amélioration des performances, une alternative serait d'utiliser substring() dans une boucle:

public String[] splitStringEvery(String s, int interval) {
    int arrayLength = (int) Math.ceil(((s.length() / (double)interval)));
    String[] result = new String[arrayLength];

    int j = 0;
    int lastIndex = result.length - 1;
    for (int i = 0; i < lastIndex; i++) {
        result[i] = s.substring(j, j + interval);
        j += interval;
    } //Add the last bit
    result[lastIndex] = s.substring(j);

    return result;
}

Exemple:

Input:  String st = "1231241251341351452342352456"
Output: 123 124 125 134 135 145 234 235 245 6.

Ce n'est pas aussi court que solution de stevevls , mais c'est beaucoup plus efficace (voir ci-dessous) et je pense que ce serait plus facile à ajuster à l'avenir, bien sûr en fonction de votre situation.


Tests de performances (Java 7u45)

2000 longue chaîne de caractères - l'intervalle est 3 .

split("(?<=\\G.{" + count + "})") performances (en millisecondes):

7, 7, 5, 5, 4, 3, 3, 2, 2, 2

splitStringEvery() (substring()) performances (en millisecondes):

2, 0, 0, 0, 0, 1, 0, 1, 0, 0

2 000 000 chaîne longue de caractères - l'intervalle est 3 .

split() performances (en millisecondes):

207, 95, 376, 87, 97, 83, 83, 82, 81, 83

splitStringEvery() performances (en millisecondes):

44, 20, 13, 24, 13, 26, 12, 38, 12, 13

2 000 000 chaîne longue de caractères - l'intervalle est 30 .

split() performances (en millisecondes):

103, 61, 41, 55, 43, 44, 49, 47, 47, 45

splitStringEvery() performances (en millisecondes):

7, 7, 2, 5, 1, 3, 4, 4, 2, 1

Conclusion:

La méthode splitStringEvery() est beaucoup plus rapide (même après les changements de Java = 7u6 ), et il augmente lorsque les intervalles deviennent plus élevés.

Code de test prêt à l'emploi:

Pastebin.com/QMPgLbG9

44
Aske B.

Vous pouvez utiliser l'opérateur d'accolade pour spécifier le nombre de fois qu'un caractère doit apparaître:

String []thisCombo2 = thisCombo.split("(?<=\\G.{" + count + "})");

L'accolade est un outil pratique car vous pouvez l'utiliser pour spécifier un nombre exact ou des plages.

29
stevevls

En utilisant Google Guava , vous pouvez utiliser Splitter.fixedLength ()

Renvoie un séparateur qui divise les chaînes en morceaux de la longueur donnée

Splitter.fixedLength(2).split("abcde");
// returns an iterable containing ["ab", "cd", "e"].
19
epoch

Si vous souhaitez créer cette chaîne d'expression régulière, vous pouvez définir la longueur de fractionnement en tant que paramètre.

public String getRegex(int splitLength)
{
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < splitLength; i++)
        builder.append(".");

    return "(?<=\\G" + builder.toString() +")";
}
0
The Cat
private String[] StringSpliter(String OriginalString) {
    String newString = "";
    for (String s: OriginalString.split("(?<=\\G.{"nth position"})")) { 
        if(s.length()<3)
            newString += s +"/";
        else
            newString += StringSpliter(s) ;
    }
    return newString.split("/");
}
0
newMaziar