问题描述
我不认为这很难,只是乏味的写道:一些小的免费(如啤酒)图书馆,我可以把一个字符串像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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!