【问题标题】:Preserving white space when using .split?使用.split时保留空白?
【发布时间】:2022-01-15 10:43:49
【问题描述】:

我正在尝试拆分一个字符串并将其存储在一个数组中,这样每个单词都存储在一个单独的索引中。我还希望存储空格和任何标点符号。

例如。 “世界你好!”

将被存储为:

array[0]: "hello"
array[1]: " "
array[2]: "world!"

我目前正在使用 .split,但不知道如何拆分字符串,以便它在单词的末尾拆分 存储空白。

strArray = str.split(" ");

【问题讨论】:

  • 你能举例说明你为什么需要这个吗?我不知道这应该有什么好处......或者至少我认为这不是要走的路
  • 您可以在单词边界"\\b" 上拆分,尽管句子要么以单词开头,要么以空格开头。然后你可以使用正则表达式前瞻/后视来达到同样的效果。

标签: java arrays string split whitespace


【解决方案1】:

为了使用正则表达式拆分字符串并保留分隔符,可能需要先行和后行:(?=\W)|(?<=\W),即拆分是由一个空字符串后跟或后跟一个非单词字符完成的:

String str = "Hello    World!";

Arrays.stream(str.split("(?=\\W)|(?<=\\W)"))
      .forEach(s -> System.out.println("'" + s + "'"));

输出:

'Hello'
' '
' '
' '
' '
'World'
'!'

更简单的版本是按照评论中的建议按字边框\b 分割,然后加入所有分隔符:

String str = "Hello    World!";
Arrays.stream(str.split("\\b"))
      .forEach(s -> System.out.println("'" + s + "'"));

输出:

'Hello'
'    '
'World'
'!'

【讨论】:

    【解决方案2】:

    您也可以随时自己拆分字符串。

    import java.util.*;
    
    class Split {
        public static void main(String... args) {
            var s = new Split();
            System.out.println(s.split(args[0]));
        }
    
        private List<String> split(String word) {
            // TODO: validate empty string
            var list = new ArrayList<String>();
            var sb = new StringBuilder();
            var inSpace = word.charAt(0) == ' ';
    
            for (char c : word.toCharArray()) {
    
                if (c == ' ' && inSpace || c != ' ' && !inSpace) {
                    sb.append(c);
                }
                if (c == ' ' && !inSpace || c != ' ' && inSpace) {
                    list.add(sb.toString());
                    sb = new StringBuilder();
                    sb.append(c);
                    inSpace = !inSpace;
                }
            }
    
            list.add(sb.toString());
            return list;
        }
    }
    

    输出:

    ~/$ java Split "hello world" 
    [hello,  , world]
    ~/$ java Split "hello         world"
    [hello,          , world]
    

    【讨论】:

      【解决方案3】:

      StringTokenizer

      构造函数StringTokenizer(String str, String delim, boolean returnDelim) 很方便。

      import java.util.*;
      public class Test {
          public static void main (String[] args) {
              StringTokenizer st = new StringTokenizer(args[1], args[0], true);
              ArrayList<String> sa = new ArrayList<String>();
              while (st.hasMoreTokens())
                  sa.add(st.nextToken());
              String[] array = sa.toArray(new String[sa.size()]);
              for (int i=0; i<array.length; i++)
                  System.out.println(String.format("array[%d] = '%s'", i, array[i]));
          }
      }
      
      $ java Test " " "a test"
      array[0] = 'a'
      array[1] = ' '
      array[2] = 'test'
      
      $ java Test " " "a  test"
      array[0] = 'a'
      array[1] = ' '
      array[2] = ' '
      array[3] = 'test'
      

      您可能会做的是测试数组的每个元素以确定它是否是分隔符,考虑到构造函数的分隔符参数的知识,这并不难。

      【讨论】:

      • 哪一个?您可能希望对此进行扩展以提高答案的质量,请参阅 How to Answer
      【解决方案4】:

      为除最后一个元素之外的每个元素添加空间

      String token=" ";
      strArray = str.split(token);
      
      for(int i=0;i<strArray.length - 2 ;i++){
        strArray[i]=strArray[i]+token
      }
      

      【讨论】:

      • 会错过在hello world 中保留多个空格(以防保留它们是相关的)
      • 所以令牌不是“”而是“\s+”
      • 甚至是 "(\s+") 这样你就可以添加整个捕获组
      • 这也将存储两个令牌["hello ", "world] 而不是三个。
      猜你喜欢
      • 1970-01-01
      • 2011-12-15
      • 2016-08-26
      • 1970-01-01
      • 2020-02-17
      • 2010-09-20
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      相关资源
      最近更新 更多