如何有效地找到最小的正int?

时间:2014-09-28 10:54:17

标签: java algorithm optimization

我正在阅读文字,我想找到第一句的结尾,此时是'。','?'的第一个索引,或者'!'在一个字符串中。所以这是我的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语句,看起来并不太整洁。我可能想在那里添加更多的句子分隔符,但我不认为这种方法非常灵活。有没有更好的方法做同样的事情?任何更短的方法来实现相同的结果? ...或者我应该尝试其他编程语言来解决这类问题?哪一个?

5 个答案:

答案 0 :(得分: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

答案 1 :(得分: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;
    }
}

答案 2 :(得分: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);

答案 3 :(得分: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

在现实生活中,这应该是一个笑话,而不是一个真正的答案{/ 3}}。

答案 4 :(得分:0)

我建议只是按字符循环字符串,并在遇到任何这些字符时停止。你现在所做的事情效率要低很多倍。