是否有任何用于解析“数字表达式”的库像Java中的1,2-9,33 [英] Are there any libraries for parsing "number expressions" like 1,2-9,33- in Java

查看:145
本文介绍了是否有任何用于解析“数字表达式”的库像Java中的1,2-9,33的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不认为这很难,只是乏味的写道:一些小的免费(如啤酒)图书馆,我可以把一个字符串像1,2-9,33,可以告诉我一个给定的数字匹配该表达式。就像大多数程序在其打印范围对话框中一样。仅匹配奇数或偶数的特殊功能,或匹配2 mod 5(或类似的东西)的每个数字都是不错的,但不是必需的。



操作我必须在这个列表上执行是否该范围包含给定(非负数)整数值;更多的操作,如最大/最小值(如果它们存在)或迭代器将是很好的,当然。



需要什么,它不占用大量的RAM,如果任何人进入1-10000000,但唯一的数字,我将要查询的是12345: - )



(要实现它,我将解析一个列表到几个(最小/最大/值/ mod)对,如1,10,0,1,1-10或11,33,1,2,1-33odd,或12,62,2,10,12-62 / 10(即12,22 ,32,...,62),然后检查所有间隔的每个数字。使用Integer.MaxValue等打开间隔。如果没有libs,任何想法可以更好/更有效?)

解决方案

我决定自己编码。使用您自己的风险: - )

  / * 
* NumberExpression.java - 一个简单的数字表达式解析器
*
*版权所有(c)2010 Michael Schierl
*
*保留所有权利。
*
*如果满足以下条件
*,则允许以源和二进制形式重新分发和使用
*修改,不论
*修改为
*
* - 源代码的再分发必须保留上述版权声明,
*此条件列表和以下免责声明。
*
* - 以二进制形式重新分发必须复制以上版权的
*通知,此条件列表和以下免责声明在
*文档和/或其他材料中提供分配。
*
* - 未经特定事先书面许可,不得将版权所有者的姓名及其
*贡献者的姓名用于批准或推广衍生自
*本软件的产品。
*
*本软件由版权所有者和贡献者
*按原样提供,任何明示或默示的担保,包括但不限于B $ b *对b $ b的适销性和适用性的默示担保*特别用途免责。在任何情况下,版权所有b $ b *持有人或贡献者对任何直接,间接,
*附带,特殊,惩戒性或后果性损害(包括但不限于,取代商品或服务的采购;使用,数据或利润的损失
或业务中断)无论如何导致和
*对任何责任理论,无论合同,严格责任或
*侵权(包括疏忽或以其他方式)以任何方式使用本软件的
*即使已被告知此类损害的可能性。
* /
包numberexpression;

/ **
*与非负数相匹配的表达式。这支持cron-like
*表达式,例如< code> 1,3-6,100-200,666,1000-3000 / 5,400- / 7< / code>,
*< code> -100,102- < /代码>或< code> *< / code> ;.奇数或偶数可以是
*,通过cron的语法进行匹配,或者用< code> e< / code>后缀一个简单的范围
*(不带步数值)或< code> o< / code> ;.
*
* @author Michael Schierl
* /
public class NumberExpression {

private final NumberRange [] ranges;
private final int min,max;

/ **
*创建一个新的{@link NumberExpression}。
*
* @param pattern
*表达式模式。
* @throws IllegalArgumentException
*如果模式格式错误
* /
public NumberExpression(String pattern){
String [] parts = pattern.toLowerCase()。分裂( , - 1);
ranges = new NumberRange [parts.length];
int min = Integer.MAX_VALUE,max = 0; (int i = 0; i< ranges.length; i ++){
String part = parts [i];

try {
if(part.equals(*)){
ranges [i] = new NumberRange(0,Integer.MAX_VALUE,0,1);
} else if(part.matches(\\ * / \\d +)){
ranges [i] = new NumberRange(0,Integer.MAX_VALUE,0,Integer。 parseInt函数(part.substring(2)));
} else if(part.matches(\\d +)){
int value = Integer.parseInt(part);
ranges [i] = new NumberRange(value,value,0,1);
} else if(part.matches(\\d * -\\d *)){
String [] limits = part.split( - ,-1) ;
int from = limits [0] .length()== 0? 0:Integer.parseInt(limits [0]);
int to = limits [1] .length()== 0? Integer.MAX_VALUE:Integer.parseInt(limits [1]);
if(to< from)
throw new IllegalArgumentException(Invalid pattern:+ part);
ranges [i] = new NumberRange(from,to,0,1);
} else if(part.matches(\\d * -\\\d * / \\d +)){
String [] rangeAndModulus = part.split( /,-1);
String [] limits = rangeAndModulus [0] .split( - ,-1);
int from = limits [0] .length()== 0? 0:Integer.parseInt(limits [0]);
int to = limits [1] .length()== 0? Integer.MAX_VALUE:Integer.parseInt(limits [1]);
int modulus = Integer.parseInt(rangeAndModulus [1]);
if(to< from)
throw new IllegalArgumentException(Invalid pattern:+ part);
ranges [i] = new NumberRange(from,to,from%modulus,modulus);
} else if(part.matches(\\d * -\\\d * [eo])){
String [] limits = part.substring(0,part。 length() - 1).split( - ,-1);
int from = limits [0] .length()== 0? 0:Integer.parseInt(limits [0]);
int to = limits [1] .length()== 0? Integer.MAX_VALUE:Integer.parseInt(limits [1]);
if(to< from)
throw new IllegalArgumentException(Invalid pattern:+ part);
ranges [i] = new NumberRange(from,to,part.charAt(part.length() - 1)=='o'?1:0,2);
} else {
throw new IllegalArgumentException(Invalid pattern:+ part);
}
max = Math.max(max,ranges [i] .getMax());
min = Math.min(min,ranges [i] .getMin());
} catch(NumberFormatException ex){
throw new IllegalArgumentException(Invalid pattern:+ part);
}
}
this.max = max;
this.min = min;
}

/ **
*检查此数字表达式是否与给定的数字匹配。
*
* @param number
*要检查的数字
* @return表达式是否匹配数字
* /
public boolean matches int number){
if(number< min || number> max)
return false;
for(int i = 0; i< ranges.length; i ++){
if(ranges [i] .matches(number))
return true;
}
返回false;
}

/ **
*返回可匹配的最小数字。
* /
public int getMinimum(){return min; }

/ **
*返回可匹配的最大数字。
* /
public int getMaximum(){return max; }

private static class NumberRange {
private final int min,max,remaining,modulus;

NumberRange(int min,int max,int remaining,int modulus){
this.min = min;
this.max = max;
this.remainder =余数
this.modulus =模数;
}

boolean matches(int number){
return number> = min&&数字< = max&&& number%modulus == remaining;
}

int getMin(){return min; }
int getMax(){return max; }
}
}


I don't think it is hard, just tedious to write: Some small free (as in beer) library where I can put in a String like 1,2-9,33- and it can tell me whether a given number matches that expression. Just like most programs have in their print range dialogs. Special functions for matching odd or even numbers only, or matching every number that is 2 mod 5 (or something like that) would be nice, but not needed.

The only operation I have to perform on this list is whether the range contains a given (nonnegative) integer value; more operations like max/min value (if they exist) or an iterator would be nice, of course.

What would be needed that it does not occupy lots of RAM if anyone enters 1-10000000 but the only number I will ever query is 12345 :-)

(To implement it, I would parse a list into several (min/max/value/mod) pairs, like 1,10,0,1 for 1-10 or 11,33,1,2 for 1-33odd, or 12,62,2,10 for 12-62/10 (i. e. 12, 22, 32, ..., 62) and then check each number for all the intervals. Open intervals by using Integer.MaxValue etc. If there are no libs, any ideas to do it better/more efficient?)

解决方案

I decided to code it myself indeed. Use at your own risk :-)

/* 
 * NumberExpression.java - a simple number expression parser
 * 
 * Copyright (c) 2010 Michael Schierl
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *   
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *   
 * - Neither name of the copyright holders nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *   
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND THE CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package numberexpression;

/**
 * An expression that matches nonnegative numbers. This supports cron-like
 * expressions, like <code>1,3-6,100-200,666,1000-3000/5,400-/7</code>,
 * <code>-100,102-</code> or <code>*</code>. Odd or even numbers can be
 * matched either by cron's step syntax, or by suffixing a simple range
 * (without step values) with <code>e</code> or <code>o</code>.
 * 
 * @author Michael Schierl
 */
public class NumberExpression {

    private final NumberRange[] ranges;
    private final int min, max;

    /**
     * Create a new {@link NumberExpression}.
     * 
     * @param pattern
     *            the expression pattern.
     * @throws IllegalArgumentException
     *             if the pattern is malformed
     */
    public NumberExpression(String pattern) {
        String[] parts = pattern.toLowerCase().split(",",-1);
        ranges = new NumberRange[parts.length];
        int min = Integer.MAX_VALUE, max = 0;
        for (int i = 0; i < ranges.length; i++) {
            String part = parts[i];
            try {
                if (part.equals("*")) {
                    ranges[i] = new NumberRange(0, Integer.MAX_VALUE, 0, 1);
                } else if (part.matches("\\*/\\d+")) {
                    ranges[i] = new NumberRange(0, Integer.MAX_VALUE, 0, Integer.parseInt(part.substring(2)));
                } else if (part.matches("\\d+")) {
                    int value = Integer.parseInt(part);
                    ranges[i] = new NumberRange(value, value, 0, 1);
                } else if (part.matches("\\d*-\\d*")) {
                    String[] limits = part.split("-", -1);
                    int from = limits[0].length() == 0 ? 0 : Integer.parseInt(limits[0]);
                    int to = limits[1].length() == 0 ? Integer.MAX_VALUE : Integer.parseInt(limits[1]);
                    if (to < from)
                        throw new IllegalArgumentException("Invalid pattern: " + part);
                    ranges[i] = new NumberRange(from, to, 0, 1);
                } else if (part.matches("\\d*-\\d*/\\d+")) {
                    String[] rangeAndModulus = part.split("/", -1);
                    String[] limits = rangeAndModulus[0].split("-", -1);
                    int from = limits[0].length() == 0 ? 0 : Integer.parseInt(limits[0]);
                    int to = limits[1].length() == 0 ? Integer.MAX_VALUE : Integer.parseInt(limits[1]);
                    int modulus = Integer.parseInt(rangeAndModulus[1]);
                    if (to < from)
                        throw new IllegalArgumentException("Invalid pattern: " + part);
                    ranges[i] = new NumberRange(from, to, from % modulus, modulus);
                } else if (part.matches("\\d*-\\d*[eo]")) {
                    String[] limits = part.substring(0, part.length() - 1).split("-", -1);
                    int from = limits[0].length() == 0 ? 0 : Integer.parseInt(limits[0]);
                    int to = limits[1].length() == 0 ? Integer.MAX_VALUE : Integer.parseInt(limits[1]);
                    if (to < from)
                        throw new IllegalArgumentException("Invalid pattern: " + part);
                    ranges[i] = new NumberRange(from, to, part.charAt(part.length() - 1) == 'o' ? 1 : 0, 2);
                } else {
                    throw new IllegalArgumentException("Invalid pattern: " + part);
                }
                max = Math.max(max, ranges[i].getMax());
                min = Math.min(min, ranges[i].getMin());
            } catch (NumberFormatException ex) {
                throw new IllegalArgumentException("Invalid pattern: " + part);
            }
        }
        this.max = max;
        this.min = min;
    }

    /**
     * Check whether this number expression matches the given number.
     * 
     * @param number
     *            the number to check against
     * @return whether the expression matches the number
     */
    public boolean matches(int number) {
        if (number < min || number > max)
            return false;
        for (int i = 0; i < ranges.length; i++) {
            if (ranges[i].matches(number))
                return true;
        }
        return false;
    }

    /**
     * Return the minimum number that can be matched.
     */
    public int getMinimum() { return min; }

    /**
     * Return the maximum number that can be matched.
     */
    public int getMaximum() { return max; }

    private static class NumberRange {
        private final int min, max, remainder, modulus;

        NumberRange(int min, int max, int remainder, int modulus) {
            this.min = min;
            this.max = max;
            this.remainder = remainder;
            this.modulus = modulus;
        }

        boolean matches(int number) {
            return number >= min && number <= max && number % modulus == remainder;
        }

        int getMin() { return min; }  
        int getMax() { return max; }
    }
}

这篇关于是否有任何用于解析“数字表达式”的库像Java中的1,2-9,33的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆