Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将区间表示法解析为番石榴范围_Java_Parsing_Guava - Fatal编程技术网

Java 将区间表示法解析为番石榴范围

Java 将区间表示法解析为番石榴范围,java,parsing,guava,Java,Parsing,Guava,我需要解析一个包含标准间隔符号的字符串(即(8100),[6,10),等等)转换为Guava Range对象。我如何在Java中执行此操作?是否有一个实用程序包可以将字符串解析为构造Guava Range对象所需的组件?如果我们查看该模式,间隔要么以'['或'开头(“,然后它后面至少跟一个数字,后面跟一个逗号,再跟一个或多个数字,最后是“]”“或“”)” 因此正则表达式将如下所示: ^[\\(|\\[](\\d+),(\\d+)[\\)|\\]]$ 在这里,它被分解为: ^ [\\(|\\[

我需要解析一个包含标准间隔符号的字符串(即(8100),[6,10),等等)转换为Guava Range对象。我如何在Java中执行此操作?是否有一个实用程序包可以将字符串解析为构造Guava Range对象所需的组件?

如果我们查看该模式,间隔要么以
'['
'开头(“
,然后它后面至少跟一个数字,后面跟一个逗号,再跟一个或多个数字,最后是“
]”“
或“
”)”

因此正则表达式将如下所示:

^[\\(|\\[](\\d+),(\\d+)[\\)|\\]]$
在这里,它被分解为:

^
 [\\(|\\[] -> start either with `'['` or `'('` (we need to escape the special characters with `\\`)
 (\\d+) -> followed by one or more digit that we capture in a group
 , -> followed by a comma
 (\\d+) -> followed again by one or more digit that we capture in another group
 [\\)|\\]] -> and that finishes either with `']'` or `')'`
$
^
$
断言all字符串与表达式匹配,而不仅仅是表达式的一部分

我们有正则表达式,耶

现在我们需要从中创建一个
模式
实例,以便能够从中获取匹配器。最后,我们检查字符串是否与模式匹配,并获取相应的组

Pattern p = Pattern.compile("^[\\(|\\[](\\d+),(\\d+)[\\)|\\]]$");
Matcher m = p.matcher("(0,100)");

if(matcher.matches()) {
    int lowerBound = Integer.parseInt(matcher.group(1));
    int upperBound = Integer.parseInt(matcher.group(2));
    System.out.println(lowerBound + "_" + upperBound);
}
以下输出
0\u 100

现在是最后一步,获取第一个和最后一个字符,并从中创建适当的范围;将所有字符放在一起:

class RangeFactory {

    private static final Pattern p = Pattern.compile("^[\\(|\\[](\\d+),(\\d+)[\\)|\\]]$");

    public static Range from(String range) {
        Matcher m = p.matcher(range);
        if(m.matches()) {
            int length = range.length();

            int lowerBound = Integer.parseInt(m.group(1));
            int upperBound = Integer.parseInt(m.group(2));

            if(range.charAt(0) == '(') {
                if(range.charAt(length - 1) == ')') {
                    return Range.open(lowerBound, upperBound);
                }
                return Range.openClosed(lowerBound, upperBound);
            } else {
                if(range.charAt(length - 1) == ')') {
                    return Range.closedOpen(lowerBound, upperBound);
                }
                return Range.closed(lowerBound, upperBound);
            }
        }
        throw new IllegalArgumentException("Range " + range + " is not valid.");
    }
}
下面是一些测试用例:

List<String> ranges =
    Arrays.asList("(0,100)", "[0,100]", "[0,100)", "(0,100]", "", "()", "(0,100", "[,100]", "[100]");

for(String range : ranges) {
    try {
        System.out.println(RangeFactory.from(range));
    } catch (IllegalArgumentException ex) {
        System.out.println(ex);
    }
}
您可以改进正则表达式(以接受具有无限边界的范围等),但它应该为您提供一个良好的起点


希望有帮助!:)

遇到了类似的问题,并提出了以下解决方案:

private static final Pattern INTERVAL_PATTERN = Pattern.compile("([\\[\\(])(-?∞?\\d*)(?:\\,|\\.\\.)(-?∞?\\d*)([\\]\\)])");

/**
 * Parses integer ranges of format (2,5], (2..5], (2,), [2..), [2..∞), [2,∞)
 *
 * @param notaiton The range notation to parse
 * @throws IllegalArgumentException if the interval is not in the defined notation format.
 */
public static Range<Integer> parseIntRange(@NonNull String notaiton) {
    Matcher matcher = INTERVAL_PATTERN.matcher(notaiton);
    if (matcher.matches()) {

        Integer lowerBoundEndpoint = Ints.tryParse(matcher.group(2));
        Integer upperBoundEndpoint = Ints.tryParse(matcher.group(3));
        if (lowerBoundEndpoint == null && upperBoundEndpoint == null) {
            return Range.all();
        }
        boolean lowerBoundInclusive = matcher.group(1).equals("[");
        boolean upperBoundInclusive = matcher.group(4).equals("]");

        //lower infinity case
        if (lowerBoundEndpoint == null) {
            if (upperBoundInclusive) {
                return Range.atMost(upperBoundEndpoint);
            } else {
                return Range.lessThan(upperBoundEndpoint);
            }
        } //upper infinity case
        else if (upperBoundEndpoint == null) {
            if (lowerBoundInclusive) {
                return Range.atLeast(lowerBoundEndpoint);
            } else {
                return Range.greaterThan(lowerBoundEndpoint);
            }
        }

        //non infinity cases
        if (lowerBoundInclusive) {
            if (upperBoundInclusive) {
                return Range.closed(lowerBoundEndpoint, upperBoundEndpoint);
            } else {
                return Range.closedOpen(lowerBoundEndpoint, upperBoundEndpoint);
            }

        } else {
            if (upperBoundInclusive) {
                return Range.openClosed(lowerBoundEndpoint, upperBoundEndpoint);
            } else {
                return Range.open(lowerBoundEndpoint, upperBoundEndpoint);
            }
        }
    } else {
        throw new IllegalArgumentException(notaiton + " is not a valid range notation");
    }
}

没有内置的实用程序对象,但它看起来像是可以用正则表达式直接完成的事情?你不需要一个完整的解析器;你只需要提取第一个括号字符、下端、上端和第二个括号字符……谢谢-我也这么想,但我知道正则表达式的框架相当缺乏。提取相关片段需要哪些正则表达式?
private static final Pattern INTERVAL_PATTERN = Pattern.compile("([\\[\\(])(-?∞?\\d*)(?:\\,|\\.\\.)(-?∞?\\d*)([\\]\\)])");

/**
 * Parses integer ranges of format (2,5], (2..5], (2,), [2..), [2..∞), [2,∞)
 *
 * @param notaiton The range notation to parse
 * @throws IllegalArgumentException if the interval is not in the defined notation format.
 */
public static Range<Integer> parseIntRange(@NonNull String notaiton) {
    Matcher matcher = INTERVAL_PATTERN.matcher(notaiton);
    if (matcher.matches()) {

        Integer lowerBoundEndpoint = Ints.tryParse(matcher.group(2));
        Integer upperBoundEndpoint = Ints.tryParse(matcher.group(3));
        if (lowerBoundEndpoint == null && upperBoundEndpoint == null) {
            return Range.all();
        }
        boolean lowerBoundInclusive = matcher.group(1).equals("[");
        boolean upperBoundInclusive = matcher.group(4).equals("]");

        //lower infinity case
        if (lowerBoundEndpoint == null) {
            if (upperBoundInclusive) {
                return Range.atMost(upperBoundEndpoint);
            } else {
                return Range.lessThan(upperBoundEndpoint);
            }
        } //upper infinity case
        else if (upperBoundEndpoint == null) {
            if (lowerBoundInclusive) {
                return Range.atLeast(lowerBoundEndpoint);
            } else {
                return Range.greaterThan(lowerBoundEndpoint);
            }
        }

        //non infinity cases
        if (lowerBoundInclusive) {
            if (upperBoundInclusive) {
                return Range.closed(lowerBoundEndpoint, upperBoundEndpoint);
            } else {
                return Range.closedOpen(lowerBoundEndpoint, upperBoundEndpoint);
            }

        } else {
            if (upperBoundInclusive) {
                return Range.openClosed(lowerBoundEndpoint, upperBoundEndpoint);
            } else {
                return Range.open(lowerBoundEndpoint, upperBoundEndpoint);
            }
        }
    } else {
        throw new IllegalArgumentException(notaiton + " is not a valid range notation");
    }
}
@Test
public void testParseIntRange_infinites_parsesOK() {
    assertThat(NumberUtils.parseIntRange("(,2)"), is(Range.lessThan(2)));
    assertThat(NumberUtils.parseIntRange("(2,)"), is(Range.greaterThan(2)));
    assertThat(NumberUtils.parseIntRange("(,2]"), is(Range.atMost(2)));
    assertThat(NumberUtils.parseIntRange("[2,)"), is(Range.atLeast(2)));
    assertThat(NumberUtils.parseIntRange("(..2)"), is(Range.lessThan(2)));
    assertThat(NumberUtils.parseIntRange("(2..)"), is(Range.greaterThan(2)));
    assertThat(NumberUtils.parseIntRange("(..2]"), is(Range.atMost(2)));
    assertThat(NumberUtils.parseIntRange("[2..)"), is(Range.atLeast(2)));

    assertThat(NumberUtils.parseIntRange("(∞,2)"), is(Range.lessThan(2)));
    assertThat(NumberUtils.parseIntRange("(2,∞)"), is(Range.greaterThan(2)));
    assertThat(NumberUtils.parseIntRange("(∞,2]"), is(Range.atMost(2)));
    assertThat(NumberUtils.parseIntRange("[2,∞)"), is(Range.atLeast(2)));
    assertThat(NumberUtils.parseIntRange("(∞..2)"), is(Range.lessThan(2)));
    assertThat(NumberUtils.parseIntRange("(2..∞)"), is(Range.greaterThan(2)));
    assertThat(NumberUtils.parseIntRange("(∞..2]"), is(Range.atMost(2)));
    assertThat(NumberUtils.parseIntRange("[2..∞)"), is(Range.atLeast(2)));

    assertThat(NumberUtils.parseIntRange("(-∞,2)"), is(Range.lessThan(2)));
    assertThat(NumberUtils.parseIntRange("(-∞,2]"), is(Range.atMost(2)));
    assertThat(NumberUtils.parseIntRange("(-∞,]"), is(Range.all()));
}

@Test
public void testParseIntRange_parsesOK() {
    assertThat(NumberUtils.parseIntRange("(-2,3)"), is(Range.open(-2, 3)));
    assertThat(NumberUtils.parseIntRange("(-2,-1)"), is(Range.open(-2, -1)));
    assertThat(NumberUtils.parseIntRange("(2,3)"), is(Range.open(2, 3)));
    assertThat(NumberUtils.parseIntRange("[2,3)"), is(Range.closedOpen(2, 3)));
    assertThat(NumberUtils.parseIntRange("(2,3]"), is(Range.openClosed(2, 3)));
    assertThat(NumberUtils.parseIntRange("[2,3]"), is(Range.closed(2, 3)));

    assertThat(NumberUtils.parseIntRange("(2..3)"), is(Range.open(2, 3)));
    assertThat(NumberUtils.parseIntRange("[2..3)"), is(Range.closedOpen(2, 3)));
    assertThat(NumberUtils.parseIntRange("(2..3]"), is(Range.openClosed(2, 3)));
    assertThat(NumberUtils.parseIntRange("[2..3]"), is(Range.closed(2, 3)));
}

@Test
public void testParseIntRange_WithInvalidStrings_failsAccordingly() {
    String[] invalidParams = {
        null, "", "(4 5", "[2,3] ", " [2,3]", "[2,3][2,3]", "[a,b]", " [2..3]", "[2.3]",
        "[3...4]", "(3 4)", "[2]", "(5,1)", "ab[2,4]", "[2,4]cd", "(2,-2)", "(2,2)"
    };
    for (String invalidParam : invalidParams) {
        try {
            NumberUtils.parseIntRange(invalidParam);
            fail("Parsing '" + invalidParam + "' did not fail");
        } catch (IllegalArgumentException ex) {
        }
    }
}