【问题标题】:How to sort the words by their frequency如何按频率对单词进行排序
【发布时间】:2014-03-19 19:10:57
【问题描述】:

我获取一个输入文本文件,将其转换为数组,对数组进行排序,然后获取每个单词的频率。我不知道如何根据它们的频率从最高到最低对它们进行排序,而不导入很多东西(这是我想要做的):

//find frequencies
    int count = 0;
    List<String> list = new ArrayList<>();
    for(String s:words){
        if(!list.contains(s)){
            list.add(s);
        }
    }
    for(int i=0;i<list.size();i++){
        for(int j=0;j<words.length;j++){
            if(list.get(i).equals(words[j])){
                count++;
            }
        }

        System.out.println(list.get(i) + "\t" + count);
        count=0;
    }

这会以未排序的顺序返回具有频率的单词,例如:

the 3
with 7
he 8

等等

我希望这样排序:

he 8
with 7
the 3

【问题讨论】:

    标签: java sorting word-frequency


    【解决方案1】:

    我建议使用一个小的帮助类:

    class WordFreq implements Comparable<WordFreq> {
       final String word;
       int freq;
       @Override public int compareTo(WordFreq that) {
         return Integer.compare(this.freq, that.freq);
       }
    }
    

    构建一个此类实例的数组,每个单词一个,然后使用Arrays.sort对数组进行排序。

    【讨论】:

      【解决方案2】:

      我是这样实现的,

      private static class Tuple implements Comparable<Tuple> {
          private int count;
          private String word;
      
          public Tuple(int count, String word) {
              this.count = count;
              this.word = word;
          }
      
          @Override
          public int compareTo(Tuple o) {
              return new Integer(this.count).compareTo(o.count);
          }
          public String toString() {
              return word + " " + count;
          }
      }
      
      public static void main(String[] args) {
          String[] words = { "the", "he", "he", "he", "he", "he", "he", "he",
                  "he", "the", "the", "with", "with", "with", "with", "with",
                  "with", "with" };
          // find frequencies
          Arrays.sort(words);
          Map<String, Integer> map = new HashMap<String, Integer>();
          for (String s : words) {
              if (map.containsKey(s)) {
                  map.put(s, map.get(s) + 1);
              } else {
                  map.put(s, 1);
              }
          }
          List<Tuple> al = new ArrayList<Tuple>();
          for (Map.Entry<String, Integer> entry : map.entrySet()) {
              al.add(new Tuple(entry.getValue(), entry.getKey()));
          }
          Collections.sort(al);
          System.out.println(al);
      }
      

      输出是,

      [the 3, with 7, he 8]
      

      【讨论】:

      • 我喜欢这种对频率进行排序的方式,但我需要输出按降序排列 - 从最大到最低,并且像我的代码中的表格一样。
      • @nanachan 然后将 compareTo 更改为 return new Integer(o.count).compareTo(this.count); 并且 toString 方法应该使用 \t
      • 如果我将 toString 设置为带有 \t 它仍然返回一个类似[he 8,with 7,the 3]的数组
      • @nanachan 删除 System.out.println(al); 并执行 for (Tuple t : al) System.out.println(t);
      【解决方案3】:

      您应该创建一个 Word 类型的对象,该对象包含单词的 String 值及其频率。

      然后您可以实现compareTo 或使用Comparator 并在您的Word 类型列表上调用Collections.sort()

      【讨论】:

        【解决方案4】:

        使用Map&lt;String, Integer&gt; 而不是将String 存储为键,并将频率存储为值,初始值为 1。如果单词已经存在,只需将值增加 1 来更新值。然后,将其转换映射到Map&lt;Integer, List&lt;String&gt;&gt;(或Guava Multimap)并使用Integer 值作为键,并使用String 键将它们存储为值。

        【讨论】: