Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何拆分字符串,包括标点符号?_Java - Fatal编程技术网

Java 如何拆分字符串,包括标点符号?

Java 如何拆分字符串,包括标点符号?,java,Java,我需要拆分一个字符串(在Java中),其中标点符号存储在与单词相同的数组中: String sentence = "In the preceding examples, classes derived from..."; String[] split = sentence.split(" "); 我需要拆分数组: split[0] - "In" split[1] - "the" split[2] - "preceding" split[3] - "examples" split[4] - ",

我需要拆分一个字符串(在Java中),其中标点符号存储在与单词相同的数组中:

String sentence = "In the preceding examples, classes derived from...";
String[] split = sentence.split(" ");
我需要拆分数组:

split[0] - "In"
split[1] - "the"
split[2] - "preceding"
split[3] - "examples"
split[4] - ","
split[5] - "classes"
split[6] - "derived"
split[7] - "from"
split[8] - "..."

有什么优雅的解决方案吗?

您可以对字符串进行清理,将所有您想要区分的标点符号替换为“,”等等

在“…”的特殊情况下,您可以执行以下操作:

// there can be series of dots
sentence.replace(".", " .").replace(". .", "..")
然后你就分手了


编辑:将单引号替换为双引号。

您需要查看以下内容:

String[] split = sentence.split(" ?(?<!\\G)((?<=[^\\p{Punct}])(?=\\p{Punct})|\\b) ?");

对于您的特殊情况,两个主要挑战是排序(例如,先是标点符号,然后是单词或其他方式)和
标点符号

剩下的部分,您可以使用

\p{Punct}
像这样:

Pattern.compile("\p{Punct}");
关于上述两项挑战:

1.订购: 您可以尝试以下操作:

private static final Pattern punctuation = Pattern.compile("\\p{Punct}");
private static final Pattern word = Pattern.compile("\\w");

public static void main(String[] args) {
    String sentence = "In the preceding examples, classes derived from...";
    String[] split = sentence.split(" ");
    List<String> result = new LinkedList<>();

    for (String s : split) {
        List<String> withMarks = splitWithPunctuationMarks(s);
        result.addAll(withMarks);
    }
}

private static void List<String> splitWithPunctuationMarks(String s) {
    Map<Integer, String> positionToString = new TreeMap<>();
    Matcher punctMatcher = punctuation.matcher(s);
    while (punctMatcher.find()) {
        positionToString.put(punctMatcher.start(), punctMatcher.group())
    }
    Matcher wordMatcher = // ... same as before
    // Then positionToString.values() will contain the 
    // ordered words and punctuation characters.
}
private static final Pattern标点=Pattern.compile(\\p{Punct});
私有静态最终模式word=Pattern.compile(\\w”);
公共静态void main(字符串[]args){
String-句子=“在前面的示例中,派生自…”的类;
String[]split=句子。split(“”);
列表结果=新建LinkedList();
用于(字符串s:拆分){
带标记列表=带标点符号拆分;
结果:添加全部(带标记);
}
}
带标点符号(字符串s)的专用静态无效列表拆分{
映射位置字符串=新树映射();
匹配器匹配器=标点符号匹配器;
while(punchmatcher.find()){
positionToString.put(putchMatcher.start(),putchMatcher.group())
}
Matcher wordMatcher=/…与之前相同
//然后positionToString.values()将包含
//有序单词和标点符号。
}
  • 您可以尝试在每次找到
    字符时,在(currentIndex-1)处查找以前出现的
    字符

  • 您可以尝试先用省略号字符替换三个点:

        String sentence = "In the preceding examples, classes derived from...";
        String[] split = sentence.replace("...", "…").split(" +|(?=,|\\p{Punct}|…)");
    

    之后,您可以保持原样,或者通过在整个阵列上运行
    replace(“…”,“…”)
    将其转换回原样。

    我相信此方法可以满足您的需要

    public static List<String> split(String str) {
        Pattern pattern = Pattern.compile("(\\w+)|(\\.{3})|[^\\s]");
        Matcher matcher = pattern.matcher(str);
        List<String> list = new ArrayList<String>();
        while (matcher.find()) {
            list.add(matcher.group());
        }
        return list;
    }
    
    名单将是

    [0] In
    [1] the
    [2] preceding
    [3] examples
    [4] ,
    [5] classes
    [6] .
    [7] .
    [8] derived
    [9] from
    [10] ...
    [11] Hello
    [12] ,
    [13] World
    [14] !
    [15] foo
    [16] !
    [17] bar
    

    现在我要说的是,要实现您想要的目标,最简单、可能也是最干净的方法是专注于在数组中查找您想要的数据,而不是找到拆分文本的位置

    我这样说是因为
    split
    引入了很多问题,例如:

    • split(“+|(?=\\p{Punct})”
      将只在空格和标点符号前面拆分,这意味着像
      “abc”def
      这样的文本将拆分为
      “abc
      def
      。因此,正如您所看到的,它不会在abc中的
      之后拆分


    • 前面的问题可以通过在这里添加另一个
      |(?另一个示例来轻松解决。此解决方案可能适用于所有组合

      import java.util.ArrayList;
      导入java.util.List;
      导入java.util.regex.Matcher;
      导入java.util.regex.Pattern;
      公共类应用程序{
      公共静态void main(字符串[]args){
      String-句子=“在前面的示例中,派生自…”的类;
      列表=使用标点符号拆分(句子);
      系统输出打印项次(列表);
      }
      公共静态列表拆分带标点符号(字符串句子){
      Pattern p=Pattern.compile(“([^a-zA-Z\\d\\s]+)”;
      String[]split=句子。split(“”);
      列表=新的ArrayList();
      用于(字符串s:拆分){
      匹配器匹配器=p.Matcher(s);
      布尔值=false;
      int i=0;
      while(matcher.find()){
      发现=真;
      添加(s.substring(i,matcher.start());
      添加(s.substring(matcher.start(),matcher.end());
      i=matcher.end();
      }
      如果(找到){
      如果(i
      输出:

      In
      (
      the
      )
      preceding
      examples
      ,
      classes
      derived
      from
      ...
      
      In
      the
      preceding
      examples
      ,
      classes
      derived
      from 
      ...
      
      In
      the
      preced
      ^^^
      in
      ##
      examp
      !
      les
      ,
      classes
      derived
      from
      ...
      
      一个更复杂的例子:

      String-sensume=“在前面的例子中,类派生自…”;
      列表=使用标点符号拆分(句子);
      系统输出打印项次(列表);
      
      输出:

      In
      (
      the
      )
      preceding
      examples
      ,
      classes
      derived
      from
      ...
      
      In
      the
      preceding
      examples
      ,
      classes
      derived
      from 
      ...
      
      In
      the
      preced
      ^^^
      in
      ##
      examp
      !
      les
      ,
      classes
      derived
      from
      ...
      

      你希望这有多聪明?你想让婆婆留下一个字吗?@storojs72你在回应谁?如果你能给出完整的要求,那就太好了。现在看来,我们给出的任何答案都不会是完美的,因为它可能无法解决其中一个
      (特殊情况…!?)
      不太可能
      !=
      不可能
      因此,您需要决定如何处理此类情况。您是否尝试过任何方法,或者您只是希望有人为您做些什么?显示您迄今为止尝试过的方法。这不是正确的Java语法。应该改为使用双引号来编写。这包含一个错误。如前所述它返回:
      [In,the,previous,examples,,classes,derived,from,…]
      。再次执行最后一次替换将修复它,但将最后一次替换更改为:
      .replace(“…”,“…”)的更优雅的解决方案是:
      :还要注意,这对正确分割逗号没有任何作用。在我看来,这就是我要寻找的。
      Arrays.stream(split.forEach(System.out::println)
      这是Java 8的语法?这也是我的第一个想法,但这无法正确处理大小写
      。此外,如果OP语句的格式不正确,例如
      foo!bar
      ,我们将以
      foo
      !bar
      结束。实际上,问题中遗漏了太多重要的细节,无法正确回答。请参阅@Mich阿科达斯answer@Pshemo我用你教给我的技巧使它正常工作(使用我能想到的边缘情况):
      \G
      :)@storojs72我重写了我的正则表达式,以正确地完成整个工作,没有任何额外的我
      In
      the
      preced
      ^^^
      in
      ##
      examp
      !
      les
      ,
      classes
      derived
      from
      ...