计算 java 中 .txt 文件中单词的频率
Counting frequency of words from a .txt file in java
我正在做 Comp Sci 作业。最后,程序将确定文件是用英语还是法语编写的。现在,我正在努力研究计算 .txt 文件中单词出现频率的方法。
我在标有 1-20 的各自文件夹中有一组英语和法语文本文件。该方法要求提供目录(在本例中为 "docs/train/eng/" 或 "docs/train/fre/")以及程序应遍历的文件数量(每个文件夹中有 20 个文件)。然后它读取该文件,将所有单词分开(我不需要担心大小写或标点符号),并将每个单词连同它们在文件中出现的次数一起放入 HashMap 中。 (关键字 = 词,值 = 频率)。
这是我为方法想出的代码:
public static HashMap<String, Integer> countWords(String directory, int nFiles) {
// Declare the HashMap
HashMap<String, Integer> wordCount = new HashMap();
// this large 'for' loop will go through each file in the specified directory.
for (int k = 1; k < nFiles; k++) {
// Puts together the string that the FileReader will refer to.
String learn = directory + k + ".txt";
try {
FileReader reader = new FileReader(learn);
BufferedReader br = new BufferedReader(reader);
// The BufferedReader reads the lines
String line = br.readLine();
// Split the line into a String array to loop through
String[] words = line.split(" ");
int freq = 0;
// for loop goes through every word
for (int i = 0; i < words.length; i++) {
// Case if the HashMap already contains the key.
// If so, just increments the value
if (wordCount.containsKey(words[i])) {
wordCount.put(words[i], freq++);
}
// Otherwise, puts the word into the HashMap
else {
wordCount.put(words[i], freq++);
}
}
// Catching the file not found error
// and any other errors
}
catch (FileNotFoundException fnfe) {
System.err.println("File not found.");
}
catch (Exception e) {
System.err.print(e);
}
}
return wordCount;
}
代码编译。不幸的是,当我要求它打印 20 个文件的所有字数统计结果时,it printed this。这完全是胡言乱语(尽管这些词肯定存在)并且根本不是我需要该方法做的事情。
如果有人能帮我调试我的代码,我将不胜感激。我已经做了很久了,一次又一次地进行测试,我准备放弃了。
如果只按space拆分,那么其他符号(括号、标点符号等...)将包含在单词中。例如:"This phrase, contains... funny stuff"
,如果用 space 拆分,您将得到:"This"
"phrase,"
"contains..."
"funny"
和 "stuff"
。
您可以通过按单词边界 (\b
) 拆分来避免这种情况。
line.split("\b");
顺便说一下,您的 if 和 else 部分是相同的。您总是将 freq 递增 1,这没有多大意义。如果单词已经在地图中,你想获取当前频率,将其加 1,并更新地图中的频率。如果没有,你把它放在地图中,值为1。
专业提示:总是 print/log 异常的完整堆栈跟踪。
我本以为会有更多这样的东西。有道理吗?
if (wordCount.containsKey(words[i])) {
int n = wordCount.get(words[i]);
wordCount.put(words[i], ++n);
}
// Otherwise, puts the word into the HashMap
else {
wordCount.put(words[i], 1);
}
如果单词已经在哈希图中,我们想要获取当前计数,向其添加 1
并用哈希图中的新计数替换单词。
如果这个词还没有出现在 hashmap 中,我们只需将它放在 map 中,并以 1
开始计数。下次我们看到同一个词时,我们将计数增加到 2
,以此类推
让我在这里把所有好的答案结合起来。
1) 拆分您的方法,每个方法处理一件事。一个将文件读入strings[],一个处理strings[],一个调用前两个。
2) 当你分裂时,深入思考你想如何分裂。正如 @m0skit0 所建议的那样,您可能应该用 \b 来解决这个问题。
3) 正如@jas 建议的那样,您应该首先检查您的地图是否已经包含该词。如果它确实增加了计数,如果没有将单词添加到地图并将其计数设置为 1。
4) 要以您可能期望的方式打印地图,请查看以下内容:
Map test = new HashMap();
for (Map.Entry entry : test.entrySet()){
System.out.println(entry.getKey() + " " + entry.getValue());
}
我正在做 Comp Sci 作业。最后,程序将确定文件是用英语还是法语编写的。现在,我正在努力研究计算 .txt 文件中单词出现频率的方法。
我在标有 1-20 的各自文件夹中有一组英语和法语文本文件。该方法要求提供目录(在本例中为 "docs/train/eng/" 或 "docs/train/fre/")以及程序应遍历的文件数量(每个文件夹中有 20 个文件)。然后它读取该文件,将所有单词分开(我不需要担心大小写或标点符号),并将每个单词连同它们在文件中出现的次数一起放入 HashMap 中。 (关键字 = 词,值 = 频率)。
这是我为方法想出的代码:
public static HashMap<String, Integer> countWords(String directory, int nFiles) {
// Declare the HashMap
HashMap<String, Integer> wordCount = new HashMap();
// this large 'for' loop will go through each file in the specified directory.
for (int k = 1; k < nFiles; k++) {
// Puts together the string that the FileReader will refer to.
String learn = directory + k + ".txt";
try {
FileReader reader = new FileReader(learn);
BufferedReader br = new BufferedReader(reader);
// The BufferedReader reads the lines
String line = br.readLine();
// Split the line into a String array to loop through
String[] words = line.split(" ");
int freq = 0;
// for loop goes through every word
for (int i = 0; i < words.length; i++) {
// Case if the HashMap already contains the key.
// If so, just increments the value
if (wordCount.containsKey(words[i])) {
wordCount.put(words[i], freq++);
}
// Otherwise, puts the word into the HashMap
else {
wordCount.put(words[i], freq++);
}
}
// Catching the file not found error
// and any other errors
}
catch (FileNotFoundException fnfe) {
System.err.println("File not found.");
}
catch (Exception e) {
System.err.print(e);
}
}
return wordCount;
}
代码编译。不幸的是,当我要求它打印 20 个文件的所有字数统计结果时,it printed this。这完全是胡言乱语(尽管这些词肯定存在)并且根本不是我需要该方法做的事情。
如果有人能帮我调试我的代码,我将不胜感激。我已经做了很久了,一次又一次地进行测试,我准备放弃了。
如果只按space拆分,那么其他符号(括号、标点符号等...)将包含在单词中。例如:"This phrase, contains... funny stuff"
,如果用 space 拆分,您将得到:"This"
"phrase,"
"contains..."
"funny"
和 "stuff"
。
您可以通过按单词边界 (\b
) 拆分来避免这种情况。
line.split("\b");
顺便说一下,您的 if 和 else 部分是相同的。您总是将 freq 递增 1,这没有多大意义。如果单词已经在地图中,你想获取当前频率,将其加 1,并更新地图中的频率。如果没有,你把它放在地图中,值为1。
专业提示:总是 print/log 异常的完整堆栈跟踪。
我本以为会有更多这样的东西。有道理吗?
if (wordCount.containsKey(words[i])) {
int n = wordCount.get(words[i]);
wordCount.put(words[i], ++n);
}
// Otherwise, puts the word into the HashMap
else {
wordCount.put(words[i], 1);
}
如果单词已经在哈希图中,我们想要获取当前计数,向其添加 1
并用哈希图中的新计数替换单词。
如果这个词还没有出现在 hashmap 中,我们只需将它放在 map 中,并以 1
开始计数。下次我们看到同一个词时,我们将计数增加到 2
,以此类推
让我在这里把所有好的答案结合起来。
1) 拆分您的方法,每个方法处理一件事。一个将文件读入strings[],一个处理strings[],一个调用前两个。
2) 当你分裂时,深入思考你想如何分裂。正如 @m0skit0 所建议的那样,您可能应该用 \b 来解决这个问题。
3) 正如@jas 建议的那样,您应该首先检查您的地图是否已经包含该词。如果它确实增加了计数,如果没有将单词添加到地图并将其计数设置为 1。
4) 要以您可能期望的方式打印地图,请查看以下内容:
Map test = new HashMap();
for (Map.Entry entry : test.entrySet()){
System.out.println(entry.getKey() + " " + entry.getValue());
}