代码之家  ›  专栏  ›  技术社区  ›  Emil

Java中的等长字符串拆分

  •  102
  • Emil  · 技术社区  · 16 年前

    如何拆分字符串 "Thequickbrownfoxjumps" java中大小相等的子查询。 如。 “快速浏览信息跳转” 等于4的大小应该给出输出。

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

    类似问题:

    Split string into equal-length substrings in Scala

    18 回复  |  直到 7 年前
        1
  •  198
  •   Alan Moore Chris Ballance    9 年前

    以下是Regex One Liner版本:

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

    \G 是一个零宽度断言,与上一个匹配结束的位置匹配。如果有的话 是 没有以前的匹配,它匹配输入的开头,与 \A . 封闭的lookbehind与最后一个匹配的末尾的四个字符的位置匹配。

    两种情况 \g 是高级regex功能,并非所有风格都支持。此外, \g 并不是跨支持它的风格一致地实现的。这个技巧(例如)在 Java ,perl,.net和jgsoft,但不在 PHP (PCRE)、Ruby 1.9+或TextMate(两者都是Oniguruma)。javascript的 /y (粘旗)不如 \g 即使JS支持lookback,也不能这样使用。

    我应该说我不一定 推荐 如果您有其他选项,则使用此解决方案。其他答案中的非regex解决方案可能更长,但它们也在自我记录;这一个只是关于 相反的 这一点。;)

    而且,这在Android中不起作用,它不支持 \g 在后面看。

        2
  •  117
  •   Jon Skeet    16 年前

    好吧,用暴力很容易做到这一点:

    public static List<String> splitEqually(String text, int size) {
        // Give the list the right capacity to start with. You could use an array
        // instead if you wanted.
        List<String> ret = new ArrayList<String>((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;
    }
    

    我觉得用regex做这个不值得。

    编辑:我不使用regex的理由:

    • 这不使用任何正则表达式的真正模式匹配。只是在数。
    • 我 犯罪嫌疑人 尽管在大多数情况下这并不重要,但上述方法会更有效。
    • 如果您需要在不同的地方使用不同的大小,您可以使用重复或助手函数来基于参数-ick构建regex本身。
    • 另一个答案中提供的regex首先没有编译(无效的转义),然后就不工作了。我的代码第一次工作。这更证明了regex和普通代码的可用性。
        3
  •  67
  •   Sean Patrick Floyd    9 年前

    这很容易 Google Guava :

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

    输出:

    Theq
    uick
    brow
    nfox
    jump
    s
    

    或者,如果需要将结果作为数组,则可以使用以下代码:

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

    参考文献:

    注意:splitter结构在上面以内联方式显示,但是由于splitter是不可变的和可重用的,因此最好将其存储在常量中:

    private static final Splitter FOUR_LETTERS = Splitter.fixedLength(4);
    
    // more code
    
    for(final String token : FOUR_LETTERS.split("Thequickbrownfoxjumps")){
        System.out.println(token);
    }
    
        4
  •  12
  •   Cowan    16 年前

    如果你使用谷歌的 guava 通用图书馆(很诚实地说,可能是任何新的Java项目) 应该 是的),这对于 Splitter 班级:

    for (String substring : Splitter.fixedLength(4).split(inputString)) {
        doSomethingWith(substring);
    }
    

    这就是 它 . 轻松如斯!

        5
  •  7
  •   Saul    16 年前
    public static String[] split(String src, int len) {
        String[] result = new String[(int)Math.ceil((double)src.length()/(double)len)];
        for (int i=0; i<result.length; i++)
            result[i] = src.substring(i*len, Math.min(src.length(), (i+1)*len));
        return result;
    }
    
        6
  •  6
  •   Grodriguez    16 年前
    public String[] splitInParts(String s, int partLength)
    {
        int len = s.length();
    
        // Number of parts
        int nparts = (len + partLength - 1) / partLength;
        String parts[] = new String[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;
    }
    
        7
  •  4
  •   pakore    16 年前

    你可以用 substring 从 String.class (处理例外情况)或 Apache lang commons (它为您处理异常)

    static String   substring(String str, int start, int end) 
    

    把它放进一个圈里,你就可以走了。

        8
  •  3
  •   Cheetah Coder    10 年前

    我希望这个简单的解决方案:

    String content = "Thequickbrownfoxjumps";
    while(content.length() > 4) {
        System.out.println(content.substring(0, 4));
        content = content.substring(4);
    }
    System.out.println(content);
    
        9
  •  3
  •   Pankaj Singhal    8 年前

    下面是一个使用Java8流的单行程序实现:

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

    它提供以下输出:

    [Theq, uick, brow, nfox, jump, s]
    
        10
  •  2
  •   Joseph Tesfaye    9 年前

    如果要将字符串平均向后拆分,例如从右向左拆分 1010001111 到 [10, 1000, 1111] ,代码如下:

    /**
     * @param s         the string to be split
     * @param subLen    length of the equal-length substrings.
     * @param backwards true if the splitting is from right to left, false otherwise
     * @return an array of equal-length substrings
     * @throws ArithmeticException: / by zero when subLen == 0
     */
    public static String[] split(String s, int subLen, boolean backwards) {
        assert s != null;
        int groups = s.length() % subLen == 0 ? s.length() / subLen : s.length() / subLen + 1;
        String[] strs = new String[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.substring(beginIndex, endIndex);
            }
        }
        return strs;
    }
    
        11
  •  1
  •   rloeffel    8 年前

    我使用下面的Java 8解决方案:

    public static List<String> splitString(final String string, final int chunkSize) {
      final int numberOfChunks = (string.length() + chunkSize - 1) / chunkSize;
      return IntStream.range(0, numberOfChunks)
                      .mapToObj(index -> string.substring(index * chunkSize, Math.min((index + 1) * chunkSize, string.length())))
                      .collect(toList());
    }
    
        12
  •  0
  •   Community Mohan Dere    9 年前

    我问@alan moore accepted solution 如何处理换行字符串。他建议使用Dotall。

    根据他的建议,我创建了一个小样本来说明这是如何工作的:

    public void regexDotAllExample() throws UnsupportedEncodingException {
        final String input = "The\nquick\nbrown\r\nfox\rjumps";
        final String 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
         */
    
    }
    

    但我喜欢@jon skeets的解决方案 https://stackoverflow.com/a/3760193/1237974 也。对于大型项目中的可维护性,不是每个人在正则表达式中都有相同的经验,我可能会使用jons解决方案。

        13
  •  0
  •   Hubbly    11 年前

    另一个强力解决方案是,

        String input = "thequickbrownfoxjumps";
        int n = input.length()/4;
        String[] num = new String[n];
    
        for(int i = 0, x=0, y=4; i<n; i++){
        num[i]  = input.substring(x,y);
        x += 4;
        y += 4;
        System.out.println(num[i]);
        }
    

    其中,代码只是通过带有子字符串的字符串

        14
  •  0
  •   Ravichandra    11 年前
        import static java.lang.System.exit;
       import java.util.Scanner;
       import Java.util.Arrays.*;
    
    
     public class string123 {
    
    public static void main(String[] args) {
    
    
      Scanner sc=new Scanner(System.in);
        System.out.println("Enter String");
        String r=sc.nextLine();
        String[] s=new String[10];
        int len=r.length();
           System.out.println("Enter length Of Sub-string");
        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.substring(f,last);
         // System.out.println(s[i]);
    
          if (last==len)break;
           f=(f+l);
        } 
        System.out.print(Arrays.tostring(s));
        }}
    

    结果

     Enter String
     Thequickbrownfoxjumps
     Enter length Of Sub-string
     4
    
     ["Theq","uick","brow","nfox","jump","s"]
    
        15
  •  0
  •   Adrian-Bogdan Ionescu    9 年前
    @Test
    public void regexSplit() {
        String source = "Thequickbrownfoxjumps";
        // define matcher, any char, min length 1, max length 4
        Matcher matcher = Pattern.compile(".{1,4}").matcher(source);
        List<String> 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);
    }
    
        16
  •  0
  •   itachi    8 年前

    下面是基于ReGEX和Java 8流的版本。值得一提的是 Matcher.results() 方法自Java 9以来可用。

    包括测试。

    public static List<String> splitString(String input, int splitSize) {
        Matcher matcher = Pattern.compile("(?:(.{" + splitSize + "}))+?").matcher(input);
        return matcher.results().map(MatchResult::group).collect(Collectors.toList());
    }
    
    @Test
    public void shouldSplitStringToEqualLengthParts() {
        String anyValidString = "Split me equally!";
        String[] expectedTokens2 = {"Sp", "li", "t ", "me", " e", "qu", "al", "ly"};
        String[] expectedTokens3 = {"Spl", "it ", "me ", "equ", "all"};
    
        Assert.assertArrayEquals(expectedTokens2, splitString(anyValidString, 2).toArray());
        Assert.assertArrayEquals(expectedTokens3, splitString(anyValidString, 3).toArray());
    }
    
        17
  •  0
  •   User8461    7 年前
    public static String[] split(String input, int length) throws IllegalArgumentException {
    
        if(length == 0 || input == null)
            return new String[0];
    
        int lengthD = length * 2;
    
        int size = input.length();
        if(size == 0)
            return new String[0];
    
        int rep = (int) Math.ceil(size * 1d / length);
    
        ByteArrayInputStream stream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_16LE));
    
        String[] out = new String[rep];
        byte[]  buf = new byte[lengthD];
    
        int d = 0;
        for (int i = 0; i < rep; i++) {
    
            try {
                d = stream.read(buf);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            if(d != lengthD)
            {
                out[i] = new String(buf,0,d, StandardCharsets.UTF_16LE);
                continue;
            }
    
            out[i] = new String(buf, StandardCharsets.UTF_16LE);
        }
        return out;
    }
    
        18
  •  0
  •   Timofey Gorshkov    7 年前

    Java 8解决方案 this 但简单一点):

    public static List<String> partition(String string, int partSize) {
      List<String> parts = IntStream.range(0, string.length() / partSize)
        .mapToObj(i -> string.substring(i * partSize, (i + 1) * partSize))
        .collect(toList());
      if ((string.length() % partSize) != 0)
        parts.add(string.substring(string.length() / partSize * partSize));
      return parts;
    }