0

我正在尝试通过此链接http://osherove.com/tdd-kata-1/解决以下测试驱动开发练习,但我被困在要求的末尾附近。

我一直害怕正则表达式,但似乎我必须学习它们。无论如何,我正在尝试执行以下操作: - 取一个字符串,从中提取数字并将它们相加。困扰我的要求是

允许像这样的多个分隔符:“//[delim1][delim2]\n” 例如“//[*][%]\n1*2%3”应该返回 6。确保您还可以处理具有长度的多个分隔符长于一个字符。

该要求意味着我必须从以换行符开头和结尾的字符串中提取delim1,等,然后我需要使用这些分隔符并提取. 每个分隔符都用方括号括起来。delim2//\n\n

现在,我怎么能用正则表达式在java中做到这一点?

到目前为止,我所拥有的是以下代码,涵盖了上述链接中的要求:

import java.util.ArrayList;

public class Calculator {

    public String getDelimiter(String input) {
        String delimiter = "";
        String changeDelimiter = input.split("\\n")[0];
        delimiter = changeDelimiter.substring(2);
        return delimiter;
    }

    public int calculate(String input) {
        String[] numbers;

        if (input.contains("//")) {
            String delimiter = getDelimiter(input);
            System.out.println("aaaaaaaaaaaaaaaaaaaaaaa : " + delimiter); //testing the value
            String calculation = input.split("\\n")[1];
            numbers = calculation.split("[" + delimiter + "]+");
            System.out.println("bbbbbbbbbbbbbbbbbbbbbbbb"); //testing the values
            for (String number : numbers) {
                System.out.print(number + ":");
                // System.out.print(Integer.parseInt(number) + " ");
            }

        } else
            numbers = input.split(",|\\n");

        if (input.isEmpty()) {
            return 0;
        }
        if (input.length() == 1) {
            return Integer.parseInt(input);
        }
        else {
            return getSum(numbers);
        }
    }

    private int getSum(String[] numbers) throws IllegalArgumentException {
        int sum = 0;
        ArrayList<Integer> negatives = new ArrayList<Integer>();
        for (int i = 0; i < numbers.length; i++) {
            if (Integer.parseInt(numbers[i]) < 0) {
                negatives.add(Integer.parseInt(numbers[i]));
            }
            if (Integer.parseInt(numbers[i]) >= 1000) {
                continue;
            } else
                sum += Integer.parseInt(numbers[i]);
        }
        if (negatives.isEmpty()) {
            return sum;
        } else {
            String negativeNumbers = "";
            for (Integer number : negatives) {
                negativeNumbers += number.toString() + " ";
            }
            throw new IllegalArgumentException("Negatives not allowed : " + negativeNumbers);
        }

    }

}
4

2 回答 2

0

您可以使用正则表达式

\d匹配单个数字

+是一个与前面的模式 1 多次匹配的量词

所以\d+会匹配 1 到多个数字


你的代码是

public int addAllInts(String s)
{
    int temp=0;
    Matcher m=Pattern.compile("\\d+").matcher();
    while(m.find())
    {
        temp+=Integer.parseInt(m.group());
    }
    return temp;
}
于 2013-07-03T14:13:32.307 回答
0

这不仅仅是匹配任何数字,但它应该适用于像“delim1”这样的分隔符,即包含数字的分隔符。我试图解释内联的模式和步骤。

    final String input = "//[delim1][delim2]\n12delim125delim2";
    // split the input string so you will get anything after // and before \n
    // and anything after \n until end of line ($)
    Pattern p = Pattern.compile("^//(.+)\\n(.*)$");
    Matcher m = p.matcher(input);
    if (!m.matches()) {
      System.out.println("Input string not valid");
      return;
    }

    String delimString = m.group(1);
    String searchString = m.group(2);

    // This matches the opening square bracket,
    // then as a capturing group, anything except a closing bracket. 
    // Finally it matches the closing bracket of the delimiter definition.
    Pattern pDelim = Pattern.compile("\\[([^\\]]+)\\]");
    Matcher mDelim = pDelim.matcher(delimString);

    // build a regex for String.split in the format: delim1|delim2|delim3|...
    String delimiters = "";
    while (mDelim.find()) {
     delimiters += (Pattern.quote(mDelim.group(1)) + "|");
    }
    delimiters = delimiters.substring(0, delimiters.length()-1);

    // split string and convert numbers to integers, then sum them up
    String[] numStrings = searchString.split(delimiters);
    int sum = 0;
    for (String num : numStrings) {
      sum += Integer.parseInt(num);
    }

    System.out.println("Sum: " + sum);

编辑/更多解释

正则表达式\\[([^\\]]+)\\]包含三个部分:

  • "\\[": 这将匹配分隔符定义的左方括号。注意两个必要的反斜杠,因为其中一个会被 Java 编译器解释。但是,我们也想匹配[正则表达式中的特殊字符。所以我们需要其中两个。
  • ([^\\]]+):外括号创建一个所谓的捕获组,您可以稍后使用Matcher.group(n)wheren是组的索引来访问。所以 1 是定义的第一组,2 是第二组,依此类推。0 返回整个匹配字符串。

    • [^\\]]+:此正则表达式将匹配分隔符定义的内容,即方括号内的所有内容。这一次,外面[]没有逃过一劫。它们具有特殊含义并定义了一个字符类。字符类将匹配其中指定的任何字符。例如[abc]将匹配aor borc但不匹配d。字符类的^开头有一个特殊的含义,它反转了字符类。所以 [^abc] 将匹配a,b或之外的任何字符c

      我们的字符类中定义的唯一字符是],因此字符类将匹配除右方括号之外的任何字符,这将结束定界符定义。附加到字符类的+意思是:匹配至少 1 个字符,或者如果可能的话更多。

  • \\]:只需匹配右方括号。

使用这个正则表达式,我们通过调用Matcher.find()and接收分隔符字符串Matcher.group(1)String.split()对其 delimiter 参数也采用正则表达式。所以现在我们需要构建一个匹配我们之前解析的任何分隔符字符串的正则表达式。Pattern.quote()用于转义分隔符字符串。如果分隔符包含将由正则表达式解释的特殊字符,这可能是必要的。|是这样一个特殊字符,它是一个or。我们构建的整个正则表达式字符串将匹配任何分隔符字符串。因此String.split()将拆分我们的分隔符上的字符串。

于 2013-07-03T14:45:11.863 回答