我有一个包含姓名和姓氏的字符串列表,我有一个自由文本。
List<String> names; // contains: "jon", "snow", "arya", "stark", ...
String text = "jon snow and stark arya";
我必须找到所有的名字和姓氏,可能还有Java Regex(所以使用Pattern和Matcher对象)。所以我想要这样的东西:
List<String> foundNames; // contains: "jon snow", "stark arya"
我已经完成了这2种可能的方法,但是没有使用Regex,它们不是静态的,因为NameFinder类的一部分有一个包含所有名称的列表“names”。
public List<String> findNamePairs(String text) {
List<String> foundNamePairs = new ArrayList<String>();
List<String> names = this.names;
text = text.toLowerCase();
for (String name : names) {
String nameToSearch = name + " ";
int index = text.indexOf(nameToSearch);
if (index != -1) {
String textSubstring = text.substring(index + nameToSearch.length());
for (String nameInner : names) {
if (name != nameInner && textSubstring.startsWith(nameInner)) {
foundNamePairs.add(name + " " + nameInner);
}
}
}
}
removeDuplicateFromList(foundNamePairs);
return foundNamePairs;
}
或以更坏(非常糟糕)的方式(创建所有可能的对):
public List<String> findNamePairsInTextNotOpt(String text) {
List<String> foundNamePairs = new ArrayList<String>();
text = text.toLowerCase();
List<String> pairs = getNamePairs(this.names);
for (String name : pairs) {
if (text.contains(name)) {
foundNamePairs.add(name);
}
}
removeDuplicateFromList(foundNamePairs);
return foundNamePairs;
}
答案 0 :(得分:0)
您可以使用名称列表创建正则表达式,然后使用find查找名称。为确保您没有重复项,您可以检查该名称是否已在找到的名称列表中。代码看起来像这样。
main()
如果您想区分大小写,请删除List<String> names = Arrays.asList("jon", "snow", "stark", "arya");
String text = "jon snow and Stark arya and again Jon Snow";
StringBuilder regexBuilder = new StringBuilder();
for (int i = 0; i < names.size(); i += 2) {
regexBuilder.append("(")
.append(names.get(i))
.append(" ")
.append(names.get(i + 1))
.append(")");
if (i != names.size() - 2) regexBuilder.append("|");
}
System.out.println(regexBuilder.toString());
Pattern compile = Pattern.compile(regexBuilder.toString(), Pattern.CASE_INSENSITIVE);
Matcher matcher = compile.matcher(text);
List<String> found = new ArrayList<>();
int start = 0;
while (matcher.find(start)) {
String match = matcher.group().toLowerCase();
if (!found.contains(match)) found.add(match);
start = matcher.end();
}
for (String s : found) System.out.println("found: " + s);
中的标记。如果所有匹配项具有相同的大小写,则可以省略while循环中的Pattern.compile()
。
但请确保列表包含2的多个列表元素(名称和姓氏),因为for循环将抛出toLowerCase()
。该命令在我的代码中也很重要。它只会按列表中出现的顺序查找名称对。如果您想同时拥有两个订单,则可以相应地更改正则表达式生成。
编辑:由于不知道名称是姓氏或名称以及构建名称/姓氏对,因此必须以不同方式完成正则表达式生成。
IndexOutOfBoundsException
此正则表达式将匹配任何给定的名称,后跟空格,然后再匹配任何名称。