在子字符串中的\b处不分割字符串,但在其他\b处分割字符串

4
你怎么将一个字符串按单词划分,但保留特定短语或术语?目前我有String[] strarr = str.split("\\b");,但我想修改正则表达式参数以实现上述操作。解决方案不一定要包括正则表达式。 例如,如果str等于"The city of San Francisco is truly beautiful!",而术语是"San Francisco",如何划分str以使得结果的String[]数组看起来像这样:["The", "city", "of", "San Francisco", "is", "truly", "beautiful!"]
在看到@Radiodef的评论后,我决定我并不真正需要正则表达式。如果有人能帮我解决这个问题,我仍然非常感激!

3
使用正则表达式无法准确地实现此操作……正则表达式匹配字符模式,而不是地名。这就是库存在的意义所在。 - Radiodef
@Radiodef 我同意正则表达式不是做这件事的正确方法,但我发布了正则表达式答案 :) - Federico Piazza
正则表达式在Java中存在许多性能问题,如此处所述 https://eyalsch.wordpress.com/2009/05/21/regex/。你甚至可以在我的回答中捕获3个单词短语或n个单词短语。只是说一下 ;) - Saumil
4个回答

1
我知道已发布的答案更好,但由于我曾经在这方面努力过,所以我想分享正则表达式答案。
因此,使用捕获组实现此目的的可能的正则表达式方法是使用以下正则表达式:
([A-Z][a-z]*(?:\s?[A-Z][a-z]+)*|[a-z!]+)

工作演示

比赛信息

MATCH 1
1.  [0-3]   `The`
MATCH 2
1.  [4-8]   `city`
MATCH 3
1.  [9-11]  `of`
MATCH 4
1.  [12-25] `San Francisco`
MATCH 5
1.  [26-28] `is`
MATCH 6
1.  [29-34] `truly`
MATCH 7
1.  [35-44] `beautiful!`

Java代码
String line = "The city of San Francisco is truly beautiful!";
Pattern pattern = Pattern.compile("([A-Z][a-z]*(?:\\s?[A-Z][a-z]+)*|[a-z!]+)");
Matcher matcher = pattern.matcher(line);

while (matcher.find()) {
    System.out.println("Result: " + matcher.group(1));
}

我也是这么想的,并且想出了一个非常类似的正则表达式:[A-Z]\\S+((\\s+[A-Z]\\S+)+)?|\\S+ - jaco0646

0

这是一个非常有趣的问题。我的方法是编写一个通用的方法,通过返回一个简单的字符串数组来帮助检测任意数量的词组。

这里有一个演示

以下是该方法:

 String[] find(String m[], String c[], String catchStr){

    String comp = c[0];
    ArrayList<String> list = new ArrayList<String>();
    for(int i=0;i<m.length;i++){

        boolean flag = false;

        //comparing if the substring matches or not
        if(comp.equals(m[i])){
            flag = true;
            for(int j=0;j<c.length;j++){
                //you can use equalsIgnoreCase() if you want to compare the string 
                //ignoring the case
                if(!m[i+j].equals(c[j])){
                    flag = false;
                    break;
                }
            }

        }

        if(flag){
            list.add(catchStr);
            i = i + c.length-1;
        }else{
            list.add(m[i]);
        }

    }

    //converting result into String array
    String finalArr[] = list.toArray(new String[list.size()]);

    return finalArr;

}

您可以将此函数称为:
String mainStr = "The city of San Francisco is truly beautiful!";
String catchStr = "San Francisco";
String mainStrArr[] = mainStr.split(" ");
String catchStrArr[] = catchStr.split(" ");

String finalArr[] = find(mainStrArr, catchStrArr, catchStr);

@javaislife,我更喜欢这个解决方案,因为它是一个更通用的解决方案,与 Evgeniy Dorofeev 给出的正则表达式不同,这个解决方案可以适用于任何带有任意短语数量的字符串。 - Saumil

0
如果只有旧金山是例外,那么这个程序就可以运行。
    String[] a = str.split("(?<!San)\\s+(?!Francisco)");

我能找到的多个排除的最短解决方案是这个

    String str = "The city of San Francisco is truly beautiful!";
    String[] exclusions = { "San Francisco", "Los Angeles" };
    List<String> l = new ArrayList<>();
    Matcher m = Pattern.compile("\\w+").matcher(str);
    while (m.find()) {
        l.add(m.group());
        for (String ex : exclusions) {
            if (str.regionMatches(m.start(), ex, 0, ex.length())) {
                l.set(l.size() - 1, ex);
                m.find();
                break;
            }
        }
    }
    System.out.println(l);

这是一个更好的方法。但是,当您包括洛杉矶时,您的正则表达式无法工作。 - Saumil
@EvgeniyDorofeev 我试图修复这个问题,但如果你觉得有用的话,我想到了\s(?=[a-z]+),尽管在of中有一个错误。 - Federico Piazza
感谢您的回复!多重排除解决方案似乎没有@Saumil Soni那样正常工作,但仍然很巧妙。我对正则表达式非常不熟悉,所以想知道如何修改第一个解决方案,使其适用于三个单词的短语(例如“纽约市”)。 - arjuns
第二个解决方案仅适用于英文字母和两个单词排除。 - Evgeniy Dorofeev

0

找到需要排除的子字符串,然后暂时删除其中的空格。一旦整个字符串已经被分割,找到先前编辑过的子字符串,通过将其替换为原始字符串来恢复其空格。

    // let's say:
    // whole = "The city of San Francisco is truly beautiful!",
    // token = "San Francisco"

    public static String[] excludeString(String whole, String token) {

        // replaces token string "San Francisco" with "SanFrancisco"
        whole = whole.replaceAll(token, token.replaceAll("\\s+", ""));

        // splits whole string using space as delimiter, place tokens in a string array
        String[] strarr = whole.split("\\s+");

        // brings "SanFrancisco" back to "San Francisco" in strarr
        Collections.replaceAll(Arrays.asList(strarr), token.replaceAll("\\s+", ""), token);

        // returns the array of strings
        return strarr;
    }

示例用法:

    public static void main(String[] args) {

        String[] arr = excludeString("The city of San Francisco is truly beautiful!", "San Francisco");
        System.out.println(Arrays.asList(arr));

    }

假设你的字符串是:"The city of San Francisco is truly beautiful!" 结果将会是:[The, city, of, San Francisco, is, truly, beautiful!]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接