【问题标题】:Count recurrent words in two files计算两个文件中重复出现的单词
【发布时间】:2015-05-07 06:19:41
【问题描述】:

我有一个代码,可以计算文件中出现的单词。我想将它与 2 个文件一起使用,并在单独的表格中显示经常性(两个文件都包含)单词。你的想法是什么,怎么可能用 2 个文件?

    while ((inputLine = bufferedReader.readLine()) != null) {
        String[] words = inputLine.split("[ \n\t\r.,;:!?(){}]");

        for (int counter = 0; counter < words.length; counter++) {
            String key = words[counter].toLowerCase();
            if (key.length() > 0) {
                if (crunchifyMap.get(key) == null) {
                    crunchifyMap.put(key, 1);
                } else {
                    int value = crunchifyMap.get(key).intValue();
                    value++;
                    crunchifyMap.put(key, value);
                }
            }
        }
    }
    Set<Map.Entry<String, Integer>> entrySet = crunchifyMap.entrySet();
    System.out.println("Words" + "\t\t" + "# of Occurances");
    for (Map.Entry<String, Integer> entry : entrySet) {
        System.out.println(entry.getKey() + "\t\t" + entry.getValue());
    }

【问题讨论】:

标签: java word-count


【解决方案1】:

您可能应该使用以下(非常粗略的)算法:

  1. 读取第一个文件并将所有单词存储在Set words中;
  2. 读取第二个文件并将所有单词存储在Set words2中;
  3. 通过保留words 中也包含在words2 中的所有单词来计算相交集:words.retainAll(words2)
  4. words 包含您的最终名单。

请注意,如果将文件读取算法放入类似的方法中,则可以重用它

public Set<String> readWords(Reader reader) {
    ....
}

计数出现频率

如果您还想知道出现频率,您应该将每个文件读入Map&lt;String, Integer&gt;,该Map&lt;String, Integer&gt; 将每个单词映射到其在该文件中的出现频率。

新的Map.merge(...) 函数(自Java 8 起)简化了计数:

Map<String, Integer> freq = new HashMap<>();
for(String word : words) {
    // insert 1 or increment already mapped value
    freq.merge(word, 1, Integer::sum);
}

然后应用以下稍作修改的算法:

  1. 读取第一个文件并将所有单词存储在Map wordsFreq1中;
  2. 读取第二个文件并将所有单词存储在Map wordsFreq2中;
  3. 从第一张地图中提取单词:Set&lt;String&gt; words = wordsFreq1.keySet()
  4. 通过保留第二个地图中的所有单词来计算交集:words.retainAll(wordsFreq2.keySet())
  5. 现在words 包含所有共同的单词,wordsFreq1wordsFreq2 包含两个文件所有单词的频率。

通过这三种数据结构,您可以轻松获取所需的所有信息。示例:

    Map<String, Integer> wordsFreq1 = ... // read from file
    Map<String, Integer> wordsFreq2 = ... // read from file

    Set<String> commonWords = new HashSet<>(wordsFreq1.keySet());
    commonWords.retainAll(wordsFreq2.keySet());

    // Map that contains the summarized frequencies of all words
    Map<String, Integer> allWordsTotalFreq = new HashMap<>(wordsFreq1);
    wordsFreq2.forEach((word, freq) -> allWordsTotalFreq.merge(word, freq, Integer::sum));

    // Map that contains the summarized frequencies of words in common
    Map<String, Integer> commonWordsTotalFreq = new HashMap<>(allWordsTotalFreq);
    commonWordsTotalFreq.keySet().retainAll(commonWords);

    // List of common words sorted by frequency:
    List<String> list = new ArrayList<>(commonWords);
    Collections.sort(list, Comparator.comparingInt(commonWordsTotalFreq::get).reversed());

【讨论】:

  • 我可以用这种方法计算出现次数吗?
  • 您可以计算两个词中出现的词数 (words.size()),但不能计算它们在两个文件中出现的频率。
  • 有什么方法可以添加这个功能吗?
【解决方案2】:

用类似的代码读取第二个文件,在前一个文件的map中找到:

while ((inputLine = bufferedReader.readLine()) != null) {
    String[] words = inputLine.split("[ \n\t\r.,;:!?(){}]");

    for (int counter = 0; counter < words.length; counter++) {
        String key = words[counter].toLowerCase();
        if (key.length() > 0) {
            if (crunchifyMap.get(key) == null) {
                continue;
            } else if(duplicateMap.get(key) == null) {
                duplicateMap.put(key, 1);
            }
        }
    }
}

Set<Map.Entry<String, Integer>> duplicateEntrySet = duplicateMap.entrySet();
System.out.println("Duplicate words:");
    for (Map.Entry<String, Integer> entry : duplicateEntrySet ) {
        System.out.println(entry.getKey()); 
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多