开发者社区> 问答> 正文

Java:计算单词的出现,程序计算“空”单词

我有一个程序可以从文本文件中输入内容,删除标点符号,然后按单个空格分割,然后将结果记入地图。我可以使用它,但是在地图中也得到空结果,我不知道会产生什么:

扫描仪接受输入:

try
        {
            Scanner input = new Scanner(file);
            String nextLine;
            while (input.hasNextLine())
            {
                nextLine = input.nextLine().trim();
                processLine(nextLine, occurrenceMap);
            }
            input.close();
        }
        catch(Exception e) { System.out.println("Something has gone wrong!");}

它来自pullinng的文本文件是圣经的国王詹姆斯版本,然后一个单独的函数处理每一行:

//String[] words = line.replaceAll("[^a-zA-Z0-9 ]", " ").toLowerCase().split("\\s+"); // runtime for  bible.txt is ~1600ms

// changed to simple iteration and the program ran MUCH faster:

char[] letters = line.trim().toCharArray();
for (int i=0; i<letters.length; i++)
{
    if (Character.isLetterOrDigit(letters[i])) {continue;}
    else {letters[i] = ' ';}
}

String punctuationFree = new String(letters);
String[] words = punctuationFree.toLowerCase().split("\\W+");

// add each word to the frequency map:
for (int i=0; i<words.length; i++)
{
    if (! map.containsKey(words[i]))
    {
        map.put(words[i], 1);
    }
    else
    {
        int value = (int)map.get(words[i]);
        map.put(words[i], ++value);
    }
}

如您所见,我首先使用全部替换完成此操作,然后我提出了自己的时髦的迭代方法(该方法似乎运行得更快)。在这两种情况下,当我使用PrintWriter打印结果时,开头都会出现一个奇怪的条目:

num occurences/ (number /word)

25307 :     // what is up with this empty value ?
1 : 000     // the results continue in sorted order
2830 : 1
2122 : 10
6 : 100
9 : 101
29 : 102
23 : 103
36 : 104
46 : 105
49 : 106

我曾尝试更改String[] words = punctuationFree.toLowerCase().split("\W+");为.split(“ \ s +”)和.split(“”),但结果中仍然有此空值。

我只想计算单词和数字的出现次数,为什么我得到这个空值?

更新:在建议Character.isLetterOrDigit()可能返回不需要的字符的情况下,我重写了检查,以便仅获取所需的字符。尽管如此,我仍然得到一个神秘的空值:

for (int i=0; i<letters.length; i++)
    {
        if ((letters[i] >= 'a' && letters[i] <= 'z') || 
           (letters[i] >= 'A' && letters[i] <= 'Z'))
           {continue;}
        else if (letters[i] >= '0' && letters[i] <= '9')
           {continue;}
        else if ((letters[i] == ' ')||(letters[i] =='\n')||(letters[i] == '\t'))
           {continue;}
        else
            letters[i] = ' ';
    }

回答来源:Stack Overflow

展开
收起
montos 2020-03-26 20:51:26 429 0
1 条回答
写回答
取消 提交回答
  • 只是猜测而已,但Character方法IsLetterOrDigit已定义为可在整个unicode范围内使用。在文档页面上,它包括所有“有效字母和十进制数字是UnicodeCategory中以下类别的成员:UppercaseLetter,LowercaseLetter,TitlecaseLetter,ModifierLetter,OtherLetter或DecimalDigitNumber。”

    我认为此方法将保留您不需要的字符(特别是ModifierLetter和/或OtherLetter),并且这些字符不包含在字体中,因此您看不到它们。

    编辑1:我测试了您的算法。事实证明,空行绕过了测试,因为它跳过了for循环。从文件行读取以下行后,您需要添加行长:

    if (nextLine.length() == 0) {continue;} 编辑2:此外,由于您正在扫描每个字符以清除“非单词和非数字”,因此您还可以合并逻辑来创建单词并将其添加到集合中。像这样:

    private static void WordSplitTest(String line) {
        char[] letters = line.trim().toCharArray();
    
        boolean gotWord = false;
    
        String word = "";
    
        for (int i = 0; i < letters.length; i++) {
            if (!Character.isLetterOrDigit(letters[i])) {
    
                if(!gotWord) {continue;}
    
                gotWord = false;
    
                AddWord(word);
            }
            if (gotWord) {
                word += Character.toString(letters[i]);
            }
        }
    }
    
    private static void AddWord(String word) {
        if (!map.containsKey(word)) {
            map.put(word, 1);
        } else {
            int value = (int) map.get(word);
            map.put(word, ++value);
        }
    }
    

    回答来源:Stack Overflow

    2020-03-28 09:34:17
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载