Java 如何拆分字符串,包括标点符号?
我需要拆分一个字符串(在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] - ",
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
”
。因此,正如您所看到的,它不会在abc中的def
之后拆分“
- 前面的问题可以通过在这里添加另一个
|(?另一个示例来轻松解决。此解决方案可能适用于所有组合
输出: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(“…”,“…”)的更优雅的解决方案是:
:还要注意,这对正确分割逗号没有任何作用。在我看来,这就是我要寻找的。
这是Java 8的语法?这也是我的第一个想法,但这无法正确处理大小写Arrays.stream(split.forEach(System.out::println)
。此外,如果OP语句的格式不正确,例如…
,我们将以foo!bar
foo
结束。实际上,问题中遗漏了太多重要的细节,无法正确回答。请参阅@Mich阿科达斯answer@Pshemo我用你教给我的技巧使它正常工作(使用我能想到的边缘情况):!bar
:)@storojs72我重写了我的正则表达式,以正确地完成整个工作,没有任何额外的我\G
In the preced ^^^ in ## examp ! les , classes derived from ...