我正在尝试创建一个简单的标记生成器,该标记可在空格上分割,小写标记,删除所有非字母字符并仅保留3个或更多字符的术语。我编写了这段代码,所有小写字母,非字母字符都可以使用,并且只能保留3个或更多字符。但是我想使用split方法,但是我不知道怎么做。请提出一些建议。
public class main {
public static final String EXAMPLE_TEST = "This Mariana John bar Barr "
+ "12364 FFFFF aaaa a s d f g.";
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(\\s[a-z]{3,20})");
Matcher matcher = pattern.matcher(EXAMPLE_TEST);
while (matcher.find()) {
System.out.print("Start index: " + matcher.start());
System.out.print(" End index: " + matcher.end() + " ");
System.out.println(matcher.group());
}
}
}
答案 0 :(得分:1)
如果您不必跟踪索引:
List<String> processed = Arrays.stream(EXAMPLE_TEST.split(" ")).map(String::toLowerCase)
.map(s -> s.replaceAll("[^a-z]", "")).filter(s -> s.length() >= 3).collect(Collectors.toList());
for (String s : processed) {
System.out.println(s);
}
但是您的示例输出也显示了索引。然后,您必须将其存储在其他容器中(例如地图):
Map<Integer, String> processed = Arrays.stream(EXAMPLE_TEST.split(" ")).collect(Collectors.toMap(s -> EXAMPLE_TEST.indexOf(s), s -> s.toLowerCase().replaceAll("[^a-z]", "")));
Map<Integer, String> filtered = processed.entrySet().stream().filter(entry -> entry.getValue().length() >= 3).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
for (Map.Entry<Integer, String> entry : filtered.entrySet()) {
System.out.println("Start index: " + entry.getKey() + " " + entry.getValue());
}
答案 1 :(得分:0)
由于您的要求在任何地方都不会说“最大20”,因此可以将[a-z]{3,20}
更改为[a-z]{3,}
,以无限制的长度。
正则表达式不能小写令牌,因此您需要分别调用toLowerCase()
。您的正则表达式只有在调用正则表达式之前 才能正常运行。如果打算在调用正则表达式后在每个令牌上调用toLowerCase()
,则需要将[a-z]
更改为[a-zA-Z]
。最简单的就是这样做。
以上表示您的代码应进行如下修改:
Pattern pattern = Pattern.compile("[a-z]{3,}");
Matcher matcher = pattern.matcher(EXAMPLE_TEST.toLowerCase());
输出
Start index: 0 End index: 4 this
Start index: 5 End index: 12 mariana
Start index: 13 End index: 17 john
Start index: 18 End index: 21 bar
Start index: 22 End index: 26 barr
Start index: 33 End index: 38 fffff
Start index: 39 End index: 43 aaaa
要使用split
执行相同的操作,您需要分割由非字母字符或最多2个连续字母字符组成的任何字符序列。
String[] split = EXAMPLE_TEST.toLowerCase().split("(?:[^a-z]+|(?<![a-z])[a-z]{1,2}(?![a-z]))+");
System.out.println(Arrays.toString(split));
输出
[this, mariana, john, bar, barr, fffff, aaaa]
说明:
(?: Start non-capturing repeating group:
[^a-z]+ Match one or more nonalphabetic characters
| Or
(?<![a-z]) Not preceded by an alphabetic character
[a-z]{1,2} Match 1-2 alphabetic characters
(?![a-z]) Not followed by an alphabetic character
)+ Match one or more of the above
注意:可以删除+
之后的[^a-z]
,因为末尾的+
仍会重复,但是正则表达式的效果应更好+
在这里。
原始代码和拆分代码之间的区别在于,如果输入以非字母字符开头,则split将返回一个空字符串作为第一个结果。