Séparer la chaîne en chaînes de longueur égale en Java

Comment diviser la chaîne "Thequickbrownfoxjumps" en sous-chaînes de taille égale en Java. Par exemple. "Thequickbrownfoxjumps" de taille égale à 4 devrait donner la sortie.

 ["Theq","uick","brow","nfox","jump","s"] 

Question similaire:

Diviser la chaîne en sous-chaînes de longueur égale dans Scala

    Voici la version one-liner de regex:

     System.out.println(Arrays.toSsortingng( "Thequickbrownfoxjumps".split("(?<=\\G.{4})") )); 

    \G est une assertion de largeur nulle correspondant à la position à laquelle la correspondance précédente a pris fin. S'il n'y avait pas de correspondance précédente, il correspond au début de l'entrée, le même que \A Le lookbehind englobant correspond à la position à quatre caractères de la fin du dernier match.

    Lookbehind et \G sont des fonctionnalités avancées de regex, non sockets en charge par toutes les versions. De plus, \G n'est pas implémenté de manière cohérente dans les versions qui le prennent en charge. Cette astuce fonctionnera (par exemple) en Java , Perl, .NET et JGSoft, mais pas en PHP (PCRE), Ruby 1.9+ ou TextMate (les deux à la fois). JavaScript /y (drapeau collant) n'est pas aussi flexible que \G , et ne pourrait pas être utilisé de cette manière même si JS supportait lookbehind.

    Je dois mentionner que je ne recommande pas nécessairement cette solution si vous avez d’autres options. Les solutions non-regex dans les autres réponses peuvent être plus longues, mais elles sont également auto-documentées; celui-ci est à peu près le contraire de cela. 😉

    En outre, cela ne fonctionne pas dans Android, qui ne prend pas en charge l'utilisation de \G dans lookbehinds.

    Eh bien, il est assez facile de le faire par force brute:

     public static List splitEqually(Ssortingng text, int size) { // Give the list the right capacity to start with. You could use an array // instead if you wanted. List ret = new ArrayList((text.length() + size - 1) / size); for (int start = 0; start < text.length(); start += size) { ret.add(text.substring(start, Math.min(text.length(), start + size))); } return ret; } 

    Je ne pense pas que cela vaille la peine d'utiliser une regex pour cela.

    EDIT: Mon raisonnement pour ne pas utiliser une regex:

    • Cela n'utilise aucune des correspondances réelles de regex. C'est juste compter.
    • Je soupçonne que ce qui précède sera plus efficace, bien que dans la plupart des cas, cela n'aura aucune importance
    • Si vous avez besoin d'utiliser des tailles de variable à différents endroits, vous avez soit une répétition, soit une fonction d'assistance pour construire la regex elle-même en fonction d'un paramètre - ick.
    • Le regex fourni dans une autre réponse ne compilait pas (échappement non valide), mais ne fonctionnait pas. Mon code a fonctionné la première fois. C'est plus une preuve de la facilité d'utilisation des regexes par rapport au code simple, IMO.

    C’est très facile avec Google Guava :

     for(final Ssortingng token : Splitter .fixedLength(4) .split("Thequickbrownfoxjumps")){ System.out.println(token); } 

    Sortie:

     Theq uick brow nfox jump s 

    Ou si vous avez besoin du résultat sous forme de tableau, vous pouvez utiliser ce code:

     Ssortingng[] tokens = Iterables.toArray( Splitter .fixedLength(4) .split("Thequickbrownfoxjumps"), Ssortingng.class ); 

    Référence:

    • Splitter.fixedLength()
    • Splitter.split()
    • Iterables.toArray()

    Remarque: La construction du séparateur est illustrée ci-dessus, mais comme les répartiteurs sont immuables et réutilisables, il est recommandé de les stocker dans des constantes:

     private static final Splitter FOUR_LETTERS = Splitter.fixedLength(4); // more code for(final Ssortingng token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){ System.out.println(token); } 

    Si vous utilisez les bibliothèques polyvalentes de goyave de Google (et honnêtement, tout nouveau projet Java devrait l’ être probablement), c’est incroyablement sortingvial avec la classe Splitter :

     for (Ssortingng subssortingng : Splitter.fixedLength(4).split(inputSsortingng)) { doSomethingWith(subssortingng); } 

    et c’est tout . Facile comme!

     public static Ssortingng[] split(Ssortingng src, int len) { Ssortingng[] result = new Ssortingng[(int)Math.ceil((double)src.length()/(double)len)]; for (int i=0; i 
     public Ssortingng[] splitInParts(Ssortingng s, int partLength) { int len = s.length(); // Number of parts int nparts = (len + partLength - 1) / partLength; Ssortingng parts[] = new Ssortingng[nparts]; // Break into parts int offset= 0; int i = 0; while (i < nparts) { parts[i] = s.substring(offset, Math.min(offset + partLength, len)); offset += partLength; i++; } return parts; } 

    Vous pouvez utiliser une subssortingng de Ssortingng.class (gestion des exceptions) ou d’ Apache lang commons (elle gère les exceptions pour vous)

     static Ssortingng subssortingng(Ssortingng str, int start, int end) 

    Mettez-le dans une boucle et vous êtes prêt à partir.

    Je préfère cette solution simple:

     Ssortingng content = "Thequickbrownfoxjumps"; while(content.length() > 4) { System.out.println(content.subssortingng(0, 4)); content = content.subssortingng(4); } System.out.println(content); 

    Dans le cas où vous souhaitez diviser la chaîne à l’inverse, par exemple de droite à gauche, par exemple pour diviser 1010001111 en [10, 1000, 1111] , voici le code:

     /** * @param s the ssortingng to be split * @param subLen length of the equal-length subssortingngs. * @param backwards true if the splitting is from right to left, false otherwise * @return an array of equal-length subssortingngs * @throws ArithmeticException: / by zero when subLen == 0 */ public static Ssortingng[] split(Ssortingng s, int subLen, boolean backwards) { assert s != null; int groups = s.length() % subLen == 0 ? s.length() / subLen : s.length() / subLen + 1; Ssortingng[] strs = new Ssortingng[groups]; if (backwards) { for (int i = 0; i < groups; i++) { int beginIndex = s.length() - subLen * (i + 1); int endIndex = beginIndex + subLen; if (beginIndex < 0) beginIndex = 0; strs[groups - i - 1] = s.substring(beginIndex, endIndex); } } else { for (int i = 0; i < groups; i++) { int beginIndex = subLen * i; int endIndex = beginIndex + subLen; if (endIndex > s.length()) endIndex = s.length(); strs[i] = s.subssortingng(beginIndex, endIndex); } } return strs; } 

    Voici une implémentation à une ligne utilisant les stream Java8:

     Ssortingng input = "Thequickbrownfoxjumps"; final AtomicInteger atomicInteger = new AtomicInteger(0); Collection result = input.chars() .mapToObj(c -> Ssortingng.valueOf((char)c) ) .collect(Collectors.groupingBy(c -> atomicInteger.getAndIncrement() / 4 ,Collectors.joining())) .values(); 

    Il donne la sortie suivante:

     [Theq, uick, brow, nfox, jump, s] 

    J’ai demandé à @Alan Moore dans un commentaire à la solution acceptée comment gérer les chaînes avec de nouvelles lignes. Il a suggéré d’utiliser DOTALL.

    En utilisant sa suggestion, j’ai créé un petit échantillon de la façon dont cela fonctionne:

     public void regexDotAllExample() throws UnsupportedEncodingException { final Ssortingng input = "The\nquick\nbrown\r\nfox\rjumps"; final Ssortingng regex = "(?<=\\G.{4})"; Pattern splitByLengthPattern; String[] split; splitByLengthPattern = Pattern.compile(regex); split = splitByLengthPattern.split(input); System.out.println("---- Without DOTALL ----"); for (int i = 0; i < split.length; i++) { byte[] s = split[i].getBytes("utf-8"); System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s); } /* Output is a single entry longer than the desired split size: ---- Without DOTALL ---- [Idx: 0, length: 26] - [B@17cdc4a5 */ //DOTALL suggested in Alan Moores comment on SO: https://stackoverflow.com/a/3761521/1237974 splitByLengthPattern = Pattern.compile(regex, Pattern.DOTALL); split = splitByLengthPattern.split(input); System.out.println("---- With DOTALL ----"); for (int i = 0; i < split.length; i++) { byte[] s = split[i].getBytes("utf-8"); System.out.println("[Idx: "+i+", length: "+s.length+"] - " + s); } /* Output is as desired 7 entries with each entry having a max length of 4: ---- With DOTALL ---- [Idx: 0, length: 4] - [B@77b22abc [Idx: 1, length: 4] - [B@5213da08 [Idx: 2, length: 4] - [B@154f6d51 [Idx: 3, length: 4] - [B@1191ebc5 [Idx: 4, length: 4] - [B@30ddb86 [Idx: 5, length: 4] - [B@2c73bfb [Idx: 6, length: 2] - [B@6632dd29 */ } 

    Mais j'aime aussi la solution @Jon Skeets sur https://stackoverflow.com/a/3760193/1237974 . Pour la maintenabilité dans les grands projets où tout le monde n'a pas la même expérience des expressions régulières, j'utiliserais probablement la solution Jons.

    Une autre solution de force brutale pourrait être,

      Ssortingng input = "thequickbrownfoxjumps"; int n = input.length()/4; Ssortingng[] num = new Ssortingng[n]; for(int i = 0, x=0, y=4; i 

    Où le code ne fait que parcourir la chaîne avec des sous-chaînes

      import static java.lang.System.exit; import java.util.Scanner; import Java.util.Arrays.*; public class ssortingng123 { public static void main(Ssortingng[] args) { Scanner sc=new Scanner(System.in); System.out.println("Enter Ssortingng"); Ssortingng r=sc.nextLine(); Ssortingng[] s=new Ssortingng[10]; int len=r.length(); System.out.println("Enter length Of Sub-ssortingng"); int l=sc.nextInt(); int last; int f=0; for(int i=0;;i++){ last=(f+l); if((last)>=len) last=len; s[i]=r.subssortingng(f,last); // System.out.println(s[i]); if (last==len)break; f=(f+l); } System.out.print(Arrays.tossortingng(s)); }} 

    Résultat

      Enter Ssortingng Thequickbrownfoxjumps Enter length Of Sub-ssortingng 4 ["Theq","uick","brow","nfox","jump","s"] 
     @Test public void regexSplit() { Ssortingng source = "Thequickbrownfoxjumps"; // define matcher, any char, min length 1, max length 4 Matcher matcher = Pattern.comstack(".{1,4}").matcher(source); List result = new ArrayList<>(); while (matcher.find()) { result.add(source.substring(matcher.start(), matcher.end())); } String[] expected = {"Theq", "uick", "brow", "nfox", "jump", "s"}; assertArrayEquals(result.toArray(), expected); } 

    Voici ma version basée sur les stream RegEx et Java 8. Il convient de mentionner que la méthode Matcher.results() est disponible depuis Java 9.

    Test inclus.

     public static List splitSsortingng(Ssortingng input, int splitSize) { Matcher matcher = Pattern.comstack("(?:(.{" + splitSize + "}))+?").matcher(input); return matcher.results().map(MatchResult::group).collect(Collectors.toList()); } @Test public void shouldSplitSsortingngToEqualLengthParts() { Ssortingng anyValidSsortingng = "Split me equally!"; Ssortingng[] expectedTokens2 = {"Sp", "li", "t ", "me", " e", "qu", "al", "ly"}; Ssortingng[] expectedTokens3 = {"Spl", "it ", "me ", "equ", "all"}; Assert.assertArrayEquals(expectedTokens2, splitSsortingng(anyValidSsortingng, 2).toArray()); Assert.assertArrayEquals(expectedTokens3, splitSsortingng(anyValidSsortingng, 3).toArray()); }