Java Regex在Text中查找所有可能的列表对

时间:2016-06-10 14:56:34

标签: java regex

我有一个包含姓名和姓氏的字符串列表,我有一个自由文本。

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;
}

1 个答案:

答案 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

此正则表达式将匹配任何给定的名称,后跟空格,然后再匹配任何名称。