Java 如何用多个分隔符拆分字符串-并知道哪个分隔符匹配
使用Java 如何用多个分隔符拆分字符串-并知道哪个分隔符匹配,java,regex,algorithm,string-parsing,string-split,Java,Regex,Algorithm,String Parsing,String Split,使用String.split可以很容易地用多个分隔符分割字符串。您只需要定义一个正则表达式,它匹配您想要使用的所有分隔符。比如说 "1.22-3".split("[.-]") 列表中的结果包含元素“1”、“22”和“3”。到目前为止还不错 但是现在我还需要知道在片段之间找到了哪一个分隔符。有没有一个简单的方法来实现这一点 我查看了String.split、其弃用的前身StringTokenizer,以及其他据信更为现代的库(例如),但没有它们,我就无法找到匹配的分隔符。我想我所看到的是错误的算
String.split
可以很容易地用多个分隔符分割字符串。您只需要定义一个正则表达式,它匹配您想要使用的所有分隔符。比如说
"1.22-3".split("[.-]")
列表中的结果包含元素“1”
、“22”
和“3”
。到目前为止还不错
但是现在我还需要知道在片段之间找到了哪一个分隔符。有没有一个简单的方法来实现这一点
我查看了
String.split
、其弃用的前身StringTokenizer
,以及其他据信更为现代的库(例如),但没有它们,我就无法找到匹配的分隔符。我想我所看到的是错误的算法。以下两步方法更为成功,而不是使用通过分隔符分割的方法:
- 首先,我实现了一个将字符串拆分为包含分隔符的标记的方法。即将
分为1.22-3
,1
,
,22
,-
3
- 然后,我实现了一个解析器来解释这个令牌流,即区分段及其分隔符
lexer的可能实现:
import java.util.ArrayList;
import java.util.List;
public final class FixedStringTokenScanner {
/**
* Splits the given input into tokens. Each token is either one of the given constant string
* tokens or a string consisting of the other characters between the constant tokens.
*
* @param input
* The string to split.
* @param fixedStringTokens
* A list of strings to be recognized as separate tokens.
* @return A list of strings, which when concatenated would result in the input string.
* Occurrences of the fixed string tokens in the input string are returned as separate
* list entries. These entries are reference-equal to the respective fixedStringTokens
* entry. Characters which did not match any of the fixed string tokens are concatenated
* and returned as list entries at the respective positions in the list. The list does
* not contain empty or <code>null</code> entries.
*/
public static List<String> splitToFixedStringTokensAndOtherTokens(final String input, final String... fixedStringTokens) {
return new FixedStringTokenScannerRun(input, fixedStringTokens).splitToFixedStringAndOtherTokens();
}
private static class FixedStringTokenScannerRun {
private final String input;
private final String[] fixedStringTokens;
private int scanIx = 0;
StringBuilder otherContent = new StringBuilder();
List<String> result = new ArrayList<String>();
public FixedStringTokenScannerRun(final String input, final String[] fixedStringTokens) {
this.input = input;
this.fixedStringTokens = fixedStringTokens;
}
List<String> splitToFixedStringAndOtherTokens() {
while (scanIx < input.length()) {
scanIx += matchFixedStringOrAppendToOther();
}
storeOtherTokenIfNotEmpty();
return result;
}
/**
* @return the number of matched characters.
*/
private int matchFixedStringOrAppendToOther() {
for (String fixedString : fixedStringTokens) {
if (input.regionMatches(scanIx, fixedString, 0, fixedString.length())) {
storeOtherTokenIfNotEmpty();
result.add(fixedString); // add string instance so that identity comparison works
return fixedString.length();
}
}
appendCharacterToOther();
return 1;
}
private void appendCharacterToOther() {
otherContent.append(input.substring(scanIx, scanIx + 1));
}
private void storeOtherTokenIfNotEmpty() {
if (otherContent.length() > 0) {
result.add(otherContent.toString());
otherContent.setLength(0);
}
}
}
}
如果您回溯
String.split(regex)
所做的事情,并记录String.split
忽略的信息,这非常简单:
String source = "1.22-3";
Matcher m=Pattern.compile("[.-]").matcher(source);
ArrayList<String> elements=new ArrayList<>();
ArrayList<String> separators=new ArrayList<>();
int pos;
for(pos=0; m.find(); pos=m.end()) {
elements.add(source.substring(pos, m.start()));
separators.add(m.group());
}
elements.add(source.substring(pos));
String source=“1.22-3”;
Matcher m=Pattern.compile(“[.-]”).Matcher(源代码);
ArrayList元素=新的ArrayList();
ArrayList分隔符=新的ArrayList();
int pos;
对于(pos=0;m.find();pos=m.end()){
添加(source.substring(pos,m.start());
分隔符。添加(m.group());
}
添加(源子字符串(pos));
在这段代码的末尾,分隔符.get(x)
生成元素.get(x)
和元素.get(x+1)
之间的分隔符。应该清楚的是,分隔符
比元素
小一项
如果希望在一个列表中包含元素和分隔符,只需更改代码,使这两个列表成为同一个列表。这些项目已按发生顺序添加。您自己的问题的答案??????/这也像它的smomebody一样?????我在这个问题上花了很长时间,只有在找到解决方案后,我才认为这个问题可能值得在这里提出。您可以用第一人称写出来mode@vks:如果它能让你快乐,我可以重写,以便清楚地知道我问了这个问题。尽管社区推荐了我最初的方法:很好!请注意:
elements
在这段代码中与String.split的结果略有不同,因为它的末尾可能有一个空的String元素。代码不会忽略尾随分隔符。但是这是好的。解决这个问题很容易,但是对于大多数应用程序来说,保持不变的是,对于x+1
元素,确实有x
分隔符更有用。如果将两者都收集到一个列表中,那么允许列表以分隔符结尾就可以了。看起来保留分隔符的要求隐含地禁止忽略尾部分隔符,否则结果将不一致。