2015-06-14 67 views
4

如何将字符串拆分为单词但保留某些短语/术语?现在,我有String[] strarr = str.split("\\b");,但我想修改正则表达式参数来完成上面提到的。 解决方案没有包括正则表达式在 b's上拆分字符串,但在子字符串 b之间没有拆分字符串

例如,如果str等于"The city of San Francisco is truly beautiful!"和术语是"San Francisco",如何使得所得到的String []数组看起来这样你拆STR:["The", "city", "of", "San Francisco", "is", "truly", "beautiful!"]


在看到@ Radiodef的评论后,我决定我并不真正需要正则表达式本身。如果有人能帮我解决这个问题,帮助仍然非常感谢!

+3

你不能用一个正则表达式准确地做到这一点...正则表达式匹配字符的模式,而不是地方的名称。这是图书馆的用途。 – Radiodef

+0

@Radiodef我同意正则表达式不是这样做的正确方法,但我发布了正则表达式答案:) –

+0

正则表达式在Java中有很多性能问题,如此处所述https://eyalsch.wordpress.com/2009/05/21/regex /。你甚至可以在我的答案中找到3个词组或短语。只是说;) –

回答

1

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

Here is a demo

下面是方法,

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); 
+0

@javaislife我更喜欢这个解决方案,因为它是一个更一般的解决方案,而不像Evgeniy Dorofeev给出的正则表达式,这个解决方案可以适用于任何字符串的任何数量的短语 – John11

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); 
+0

这是一个更好的方法。然而,当你包括洛杉矶你的正则表达式不起作用 –

+0

你是对的,willtry修复 –

+0

@EvgeniyDorofeev我试图解决这个问题,但万一你觉得它很有用,我想出了'\ s(?= [az] +) '虽然''有'' –

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!]

1

我知道张贴的答案是更好,但因为我挣扎几乎没有反对这个,我也想分享正则表达式的答案。

所以,一个更多钞票的正则表达式的方法来使用捕获组实现这一目标是使用这个正则表达式:

([A-Z][a-z]*(?:\s?[A-Z][a-z]+)*|[a-z!]+) 

Working demo

匹配信息

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)); 
} 
+0

我在想同样的思路,并且提出了一个非常相似的RegEx:'[AZ] \\ S +((\\ s + [AZ] \\ S +)+ )?| \\ S +' – jaco0646

+0

@ jaco0646哈哈,这是一个很好的正则表达式练习 –