2014-09-28 80 views
3

我正在閱讀第一句話結尾的文本,此處爲'。','?'或'!'的第一個索引。在一個字符串中。所以這裏是我的Java代碼:如何有效地找到最小的正整數?

int next = -1; 
int nextQ = text.indexOf("? "); 
int nextE = text.indexOf("! "); 
int nextDot = text.indexOf(". "); 
if (nextDot > 0) { 
    next = nextDot; 
    if (nextQ > 0){ 
     if (nextQ < next) {next = nextQ;} 
     if (nextE > 0) { 
      if (nextE < next) {next = nextE;} 
     } 
    } else if (nextE > 0){ 
     if (nextE < next) {next = nextE;} 
    } 
} else if (nextQ > 0){ 
    next = nextQ; 
    if (nextE > 0 && nextE < next){next = nextE;} 
} else if (nextE > 0) { next = nextE;} 

我相信代碼有效,但總共有10條if語句,看起來不太整潔。我可能想在那裏添加更多的句子分隔符,但我不認爲這種方法非常靈活。有沒有更好的方法來做同樣的事情?達到相同結果的任何更短的方式? ...或者我應該嘗試一些其他編程語言來解決這類問題嗎?哪一個?

+1

'我應該爲這類問題嘗試其他編程語言嗎?哈哈,不要因爲你被困在某些東西而改變語言。 – Dici 2014-09-28 11:02:13

+1

'return 1'呢?這是我讀書的標題。 – maaartinus 2014-09-28 14:45:37

回答

8

我建議使用正則表達式一次搜索任何這些分隔符。

String text = <TEXT>; 
int next; 
Pattern p = Pattern.compile("\\? |! |\\. "); 
Matcher m = p.matcher(text); 
if (m.find()) { 
    int next = m.start(); 
} else next = -1; 

您可以更改正則表達式來精確調整匹配的內容。例如,我建議不要在分隔符後面需要一個空格,而是需要任何空格字符,以便換行符或製表符也可以工作。這將如下:"\\?\\s|!\\s|\\.\\s"。您將能夠以類似的方式添加額外的分隔符,並且稍加額外的工作就能夠檢測到觸發了哪個分隔符。

Pattern類中Java正則表達式的文檔是here和有用的教程here

+0

它在模式讀取'「\\?|!| \\。」之後有效。「我還不明白爲什麼有些角色必須逃脫兩次,但我會繼續閱讀。我以前甚至都不知道正則表達式類。謝謝! – 2014-09-28 16:43:14

+0

哦,是的,對不起。我忘了反斜槓將需要在Java字符串中轉義!我已經編輯了答案來反映這一點。 – gandaliter 2014-09-28 23:31:02

3

使用Math.min和一個小修改。

首先,打開-1到大正整數:

int largeMinusOne(int a) 
{ 
    return a==-1 ? 9999999 : a; 
} 

int nextQ = largeMinusOne(text.indexOf("? ")); 
int nextE = largeMinusOne(...); 
int nextDot = largeMinuseOne(...); 

現在:

int next = Math.min(Math.min(nextQ, nextE), nextDot); 
+0

謝謝!除了沒有發現分隔符(文件結束,亞洲語言等)的情況外,它看起來很好。但是,如果我在最後測試9999999,它可能會起作用。 – 2014-09-29 16:28:29

+0

嗯,是的,如果沒有分隔符,結果是9999999。 – zmbq 2014-09-29 18:18:30

5

使用方法來保持乾燥:

int firstDelimiterIndex(String s) { 
    return minIndex(s.indexOf(". "), minIndex(s.indexOf("? "), s.indexOf("! "))); 
} 

int minIndex(int a, int b) { 
    if (a == -1) return b; 
    if (b == -1) return a; 
    return Math.min(a, b); 
} 

,或者選擇更快的算法:

for (int i = 0; i < s.length; i++) { 
    switch (s.charAt(i)) { 
    case '.': 
    case '?': 
    case '!': 
     if (i + 1 < s.length() && s.charAt(i + 1) == ' ') 
      return i; 
    } 
} 
+0

你的第二個算法忽略空白。 – maaartinus 2014-09-28 14:48:11

2

你可能喜歡只篩選出價值,這是不正常(== -1)(Java的8):

int nextQ = text.indexOf("? "); 
int nextE = text.indexOf("! "); 
int nextDot = text.indexOf(". "); 
OptionalInt res = IntStream.of(nextQ, nextE, nextDot).filter(i -> i != -1).min(); 
if (res.isPresent()) 
    // ok, using res.get() 
else 
    // none of these substrings found 

它更像是一個笑話,不是真正的答案,在現實生活中gandaliter的應該使用答案。

+0

感謝您的「笑話」:)我可能實際上需要這些新類,一旦我找出他們在哪裏,以及正則表達式包更好。 – 2014-09-29 16:38:43

0

我會建議只循環字符串字符並停止當你遇到任何這些字符。你現在正在做的事情效率低了許多倍。