【问题标题】:Java Scanner DilimiterJava 扫描器分隔符
【发布时间】:2013-02-21 16:30:17
【问题描述】:

我正在使用 Scanner 和 Delimiter 来标记我的 .txt 文件(这是我必须做的功课)。该文件的第一个版本如下所示:

5,5,5,6,5,8,9,5,6,8, good, very good, excellent, good
7,7,8,7,6,7,8,8,9,7,very good, Good, excellent, very good
8,7,6,7,8,7,5,6,8,7 ,GOOD, VERY GOOD, GOOD, AVERAGE
9,9,9,8,9,7,9,8,9,9 ,Excellent, very good, very good, excellent
7,8,8,7,8,7,8,9,6,8 ,very good, good, excellent, excellent
6,5,6,4,5,6,5,6,6,6 ,good, average, good, good
7,8,7,7,6,8,7,8,6,6 ,good, very good, good,  very good
5,7,6,7,6,7,6,7,7,7  ,excellent, very good, very good, very good

而我用useDelimiter("[ ]*(,)[ ]*")第二个版本的文件看起来是这样的:

5 5 5 6 5 8 9 5 6 8 good, very good, excellent, good
7 7 8 7 6 7 8 8 9 7 very good, Good, excellent, very good
8 7 6 7 8 7  5 6 8 7 GOOD, VERY GOOD, GOOD, AVERAGE
9 9 9 8 9 7 9  8 9 9 Excellent, very good, very good, excellent
7 8 8 7 8 7 8 9 6 8 very good, good, excellent, excellent
6 5 6 4 5 6 5 6 6 6 good, average, good, good
7  8 7 7 6 8 7 8 6 6 good, very good, good,  very good
5 7 6 7 6 7 6 7 7 7  excellent, very good, very good, very good

我想不出一个正则表达式来帮助我用空格分隔数字和用逗号分隔单词。基本上我需要一个有 14 个值的数组(非常好是一个变量)

注意有多个空格(这样做是为了让我们更难)。

因此,我们将不胜感激。

附:我们只允许使用分隔符(不能分割等)

【问题讨论】:

  • 正则表达式有 'space' (\s) 和 'word' (\w) 和 'digit' (\d) 和 'word boundary' (\b) 字符类可能对您有所帮助.
  • 你想在最后的数字和第一个单词之间加逗号吗?
  • 我不需要在文件中添加任何东西,我只需要提取值并将它们放入一个多维数组中,在这种情况下它将是 int [8][14],单词将替换为适当的数字。

标签: java regex parsing tokenize delimiter


【解决方案1】:

这应该可行,关键是正向向后看 ((<?=)) 和交替 (|):

String input = "9 9 9 8 9 7 9  8 9 9 Excellent, very good, very good, excellent";
Scanner s = new Scanner(input).useDelimiter("(?<=\\d)[\\s,]+|\\s*,\\s*");
while (s.hasNext()) {
    System.out.println("Token: ." + s.next() + ".");
}

打印:

Token: .9.
Token: .9.
Token: .9.
Token: .8.
Token: .9.
Token: .7.
Token: .9.
Token: .8.
Token: .9.
Token: .9.
Token: .Excellent.
Token: .very good.
Token: .very good.
Token: .excellent.

【讨论】:

    【解决方案2】:

    你可以试试这个(((?&lt;=[0-9]+)\s*(?=[0-9]+))|(,\s*(?=[a-zA-Z]+))|((?&lt;=[0-9]+)\s*(?=[a-zA-Z]+))),看起来很糟糕,但应该可以

    【讨论】:

    • 首先,这是错误的。我猜你的意思是(\s*,\s*)|(\s+)。但这也行不通。它将very good 分成两个标记。
    • 数字似乎没问题,但每个字符串只包含 1 个字母。
    • 效果很好,但如果他让我解释一下,我不知道从哪里开始嘿嘿:)
    • 确实,死了| (交替)有点像“或”条件?
    【解决方案3】:

    请注意,Scanner 允许您随时更改分隔符。如果您可以依赖输入文本总是在开头有 10 个数字,在结尾有 4 个单词组,那么您可以简单地从一个仅在空格 (\s+) 上分割的分隔符开始,然后在 10 次调用 nextInt() 之后,切换到分隔符 逗号和空格 (\s*,\s*)。

    类似:

    String input = "5 5 5 6 5 8 9 5 6 8 good, very good, excellent, good";
    Scanner scanner = new Scanner(input).useDelimiter("\\s+");
    int[] results = new int[14];
    for (int i = 0; i < 10; ++i) {
        results[i] = scanner.nextInt();
    }
    scanner.useDelimiter("\\s*,\\s*");
    scanner.skip("\\s*");
    for (int i = 10; i < 14; ++i) {
        String wordPhrase = scanner.next();
        int wordValue;
        if ("average".equalsIgnoreCase(wordPhrase))
            wordValue = 1;
        else if ("good".equalsIgnoreCase(wordPhrase))
            wordValue = 2;
        else if ("very good".equalsIgnoreCase(wordPhrase))
            wordValue = 3;
        else if ("excellent".equalsIgnoreCase(wordPhrase))
            wordValue = 4;
        else
            wordValue = 0;
        results[i] = wordValue;
    }
    

    也可以使用 zero-width lookaround assertions 使用单个分隔符正则表达式来执行此操作,但这对于简单的作业问题可能有点高级。

    【讨论】:

    • 感谢您的建议,为什么我之前没有想到 :) 我有一个问题,第 10 个索引似乎总是为 0。
    • 啊,哎呀,我猜当你切换分隔符时,Scanner 不会占用最后一个数字和第一个单词之间的空格,所以它会得到类似“`good@ 987654328@Scanner` 在更改分隔符后跳过空格。
    【解决方案4】:
    String[] str = expression.split("(,\\s+)|(\\s+)");
    

    试试这个:

    【讨论】:

    • 再次非常好的被拆分成单独的令牌,它应该是一个单独的。
    猜你喜欢
    • 1970-01-01
    • 2014-04-03
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 2012-02-28
    • 2011-01-23
    相关资源
    最近更新 更多