正则表达式查找数字是否在一个范围内,例如1,3,10-15,17

时间:2014-07-28 21:33:40

标签: sql regex oracle plsql

我需要找到一种方法如何检查给定数字是否包含在一串数字和范围中。

这是一个例子: 包含数字和范围的字符串是“1,3,10-15,17”,问题可能是例如“13列入名单吗?”

在这种情况下答案是肯定的,因为它在10-15的范围内。例如,它不可能是例如16号。

就我的目的而言,返回可以翻译为“是”或“否”的东西就足够了。

任何帮助解决这个问题都表示赞赏。

由于

====根据收到的答案进行修改。====

我最终得到的解决方案基于Java存储过程+ PL / SQL Wrapper。这是代码:

create or replace and compile java source named "RegExp" as
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegExp
{
  private static  Pattern P = Pattern.compile("(\\d+)-(\\d+)");

  public static int inRange (int p1, java.lang.String p2)
  {
    int iReturn = -1;
         int input;

         String[] sa;
         sa = p2.split(",");
         Set<Integer> is = new HashSet<Integer>();

         input = p1;

        for ( String s : sa)
        {
             Matcher m = P.matcher(s);
            if (m.find())
            {
                 int start = Integer.parseInt(m.group(1));
                 int end = Integer.parseInt(m.group(2));
                for (int i = start; i <= end; i++)
                {
                    is.add(i);
                }
            }
            else
            {
                is.add(Integer.parseInt(s));
            }
        }

        if (is.contains(input))
        {
           // System.out.format("Found %d in the set %s", input, is);
            iReturn = 1;
        }
        else
        {
           // System.out.format("Didn't find %d in set %s", input, is);
            iReturn = 0;
        }
        return iReturn;

  }

};

这是PL / SQL Wrapper

CREATE OR REPLACE FUNCTION InRange (p1  IN  number, p2  IN  VARCHAR2) RETURN NUMBER
AS LANGUAGE JAVA 
NAME 'RegExp.inRange (int, java.lang.String) return int';

这是一个示例SQL语句:

SELECT InRange(13,'1,3,10-15,17') FROM   DUAL;

这返回一(1),因为数字13的范围是10-15

以下返回零(0),因为6不在列表中

SELECT InRange(6,'1,3,10-15,17') FROM   DUAL;

===更新II ====
虽然我不是Java程序员 - 所以随意增强代码 - 我确实创建了一个类似的简单函数来处理字符。

public static int inRangeString (java.lang.String p1, java.lang.String p2)
  {
      int iReturn = -1;


      String[] sa;
      sa = p2.split(",");

      Set<String> is = new HashSet<String>();


      for ( String s : sa)
        {
                 is.add(s);
        }

       if (is.contains(p1)) {
          iReturn = 1;  
              // value is valid  
          } else {  
                    iReturn = 0;
              // value is invalid  
          }  

       return iReturn;
  }

3 个答案:

答案 0 :(得分:1)

正则表达式是惯用解决方案的一部分。

但它们绝不是唯一的一部分。正则表达式用于模式匹配,而不是用于执行您需要的任意逻辑。

惯用解决方案

import javax.annotation.Nonnull;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import com.google.common.collect.TreeRangeSet;

public class Q25004732
{
    private static final Pattern RANGE = Pattern.compile("(?i)^(?=[a-z]+-[a-z]+$|\\d+-\\d+$)([a-z\\d]+)-([a-z\\d]+)$");

    public static void main(final String[] args)
    {
        final String[] sa = "1,3,10-15,17,A,b,XX-ZZ,z".split(",");
        final RangeSet<String> rs = TreeRangeSet.create();
        for (final String s : sa)
        {
            final Matcher m = RANGE.matcher(s);
            if (m.find())
            {
                rs.add(Range.closed(m.group(1), m.group(2)));
            }
            else
            {
                rs.add(Range.closed(s, s));
            }
        }
        report("13", rs);
        report("A", rs);
        report("XY", rs);
        report("c", rs);
        report("42", rs);
    }

    private static void report(@Nonnull final String input, @Nonnull final RangeSet<String> rs)
    {
        if (rs.contains(input))
        {
            System.out.format("Found %s in the set %s", input, rs);
        }
        else
        {
            System.out.format("Didn't find %s in set %s", input, rs);
        }
        System.out.println();
    }
}

预期产出:

Found 13 in the set [[1‥1], [10‥15], [17‥17], [3‥3], [A‥A], [XX‥ZZ], [b‥b], [z‥z]]
Found A in the set [[1‥1], [10‥15], [17‥17], [3‥3], [A‥A], [XX‥ZZ], [b‥b], [z‥z]]
Found XY in the set [[1‥1], [10‥15], [17‥17], [3‥3], [A‥A], [XX‥ZZ], [b‥b], [z‥z]]
Didn't find c in set [[1‥1], [10‥15], [17‥17], [3‥3], [A‥A], [XX‥ZZ], [b‥b], [z‥z]]
Didn't find 42 in set [[1‥1], [10‥15], [17‥17], [3‥3], [A‥A], [XX‥ZZ], [b‥b], [z‥z]]

取决于:

Google Guava

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>[17.0,)</version>
</dependency>

FindBugs

<dependency>
    <groupId>com.google.code.findbugs</groupId>
    <artifactId>findbugs</artifactId>
    <version>[3.0.0,)</version>
</dependency>

我的Stackoverflow GitHub存储库中提供了源代码和其他答案。

答案 1 :(得分:1)

唯一的方法是将范围转换为模式(显然),因为你需要忘记你正在处理整数,但只看到数字为&#34;正常字符&#34;。对于您的示例范围:

^(?:1[0-57]?|3)$

注意:正则表达式显然不是检查整数是否在数值范围内的方法。在现实生活中,你将使用良好的旧条件。

答案 2 :(得分:-1)

这不仅仅是一个正则表达式。你可以做的是使用正则表达式(虽然在这种情况下是过度杀伤)来提取数字,将它们分成两类:数字和范围。然后,您可以使用它来确定列表中是否有数字。