2013-06-18 92 views
2

方法getPolygonPoints(不定數)(見下文)就成了一個字符串名稱作爲參數,它看起來是這樣的:正則表達式 - 提取命中

points={{-100,100},{-120,60},{-80,60},{-100,100},{-100,100}} 

的第一個數字代表x座標時,第二個是y座標。例如,第一點是

x=-100 
y=100 

第二點是

x=-120 
y=60 

等。

現在我想提取字符串的點,並把它們放到一個ArrayList中,其中有看起來像這樣結尾:

[-100, 100, -120, 60, -80, 60, -100, 100, -100, 100] 

特別之處這裏,這點的數量給定的字符串改變,並不總是相同的。

我已經寫以下代碼:

private ArrayList<Integer> getPolygonPoints(String name) { 
    // the regular expression 
    String regGroup = "[-]?[\\d]{1,3}"; 
    // compile the regular expression into a pattern 
    Pattern regex = Pattern.compile("\\{(" + regGroup + ")"); 
    // the mather 
    Matcher matcher; 

    ArrayList<Integer> points = new ArrayList<Integer>(); 

    // matcher that will match the given input against the pattern 
    matcher = regex.matcher(name); 
    int i = 1; 
    while(matcher.find()) { 
     System.out.println(Integer.parseInt(matcher.group(i))); 
     i++; 
    } 
    return points; 
} 

第一x座標被正確地提取,但隨後拋出IndexOutOfBoundsException。我認爲會發生,因爲組2沒有定義。 我想起初我必須數點,然後遍歷這個數字。在迭代內部,我會用一個簡單的add()將int值放入ArrayList中。但我不知道該怎麼做。也許我現在不明白正則表達式的一部分。特別是這些小組如何工作。

請幫忙!

+1

你的正則表達式中只有1個組是用()括起來的部分,所以你不能訪問組2或3,因爲它不在那裏。只需在匹配循環中用matcher.group(1)替換matcher.group(1) – Regenschein

+0

爲什麼不做SPLIT和REPLACE? – NeverHopeless

回答

0

如何在短短的一行做:

List<String> list = Arrays.asList(name.replaceAll("(^\\w+=\\{+)|(\\}+$)", "").split("\\{?,\\}?")); 

你的整個方法,然後將:

private ArrayList<Integer> getPolygonPoints(String name) { 
    return new ArrayList<String>(Arrays.asList(name.replaceAll("(^\\w+=\\{+)|(\\}+$)", "").split("\\{?,\\}?"))); 
} 

該作品以第一剝離的開頭和結尾的文本,然後在逗號分割可選地被大括號包圍。

順便說一句你真的應該返回抽象類型List,而不是具體的實現ArrayList

+0

此外,輸入字符串以'points = {'開頭,不是大括號。 – millimoose

+0

@millimoose我誤解了問題,我修復了領先的「points =」部分。我現在正在返回一個ArrayList。謝謝。 – Bohemian

4

你似乎不瞭解正則表達式API的部分是每次調用find()時捕獲組編號「重置」。或者換一種說法:捕獲組的編號是其在模式中的位置,而不是在輸入字符串中的位置。

你也是這樣做的錯誤方式。你應該匹配你正在尋找的整個結構,在這個例子中是{x,y}對。我假設你不想驗證整個字符串的格式,所以我們可以忽略外括號和逗號:

Pattern p = Pattern.compile("\\{(-?\\d+),(-?\\d+)\\}"); 
Matcher m = p.matcher(name); 

while (m.find()) { 
    String x = m.group(1); 
    String y = m.group(2); 
    // parse and add to list 
} 

或者,因爲你不關心哪個座標是X和其是Y,你甚至可以這樣做:

Matcher m = Pattern.compile("-?\\d+").matcher(name); 
while (m.find()) { 
    String xOrY = m.group(); 
    // parse etc. 
} 

現在,如果你想驗證輸入,以及,我會說這是一個單獨的關注,我不一定會嘗試這樣做在同一步驟解析以保持正則表達式可讀。 (這可能是可能在這種情況下,但如果你不需要它,爲什麼擺在首位打擾。)

+0

有趣的解決方案 –

4
String points = "{{-100,100},{-120,60},{-80,60},{-100,100},{-100,100}}"; 

String[] strs = points.replaceAll("(\\{|\\})", "").split(","); 

ArrayList<Integer> list = new ArrayList<Integer>(strs.length); 

for (String s : strs) 
{ 
    list.add(Integer.valueOf(s)); 
} 
+0

+1:也是一種很好的「自由主義」方法。 – millimoose

+0

+1這是我想要的,如果可以採用的話,需要OP的確認。 – NeverHopeless

0

您也可以嘗試這個表達式:

((-?\d+)\s*,\s*(-?\d+)) 

它會給你三個組:

Group 1 : x 
Group 2 : y 
Group 3 : x,y 

你可以使用哪一個是你需要的。

+0

我建議在這種情況下使用命名組。 RE不需要記住嵌套捕獲組的編號是多麼的複雜。 – millimoose