【问题标题】:Comparing two lists of Strings for similar words and measuring frequency of occurring words - JAVA比较相似词的两个字符串列表并测量出现词的频率 - JAVA
【发布时间】:2013-01-09 15:35:09
【问题描述】:

我意识到我在这里同时问了两个不同的问题,但我认为它们是相关的(即使只是轻微的)。 无论如何,我想做的是比较两个字符串列表(不一定是 Java 列表)并删除两个列表中出现的单词。我正在考虑使用ArrayListHashSetHashSet,因为列表没有排序,但我对HashSet 的问题是我读过它们不允许重复。这与我的其他要求略有冲突,因为我希望能够计算每个单词出现的次数,但只显示一次……如果这有意义的话。 想一个 WordCloud 的例子。

这是我目前拥有的,将两个文本文件的内容保存到两个ArrayLists:

ArrayList<String> words = new ArrayList<String>();
        File file = new File(fileName);
        Scanner scanner = new Scanner(file).useDelimiter("$");
        while(scanner.hasNext())
        {               
            String wrd = scanner.nextLine();
            words.add(wrd);
        }

我不得不使用两种不同的方式来保存数据,因为这两个文本文件的结构不同

ArrayList<String> webWords = new ArrayList<String>();
    File webFile = new File(webFileName);
    BufferedReader br = new BufferedReader(new FileReader(webFileName));
    String testLine = "", str = "";
    int count = 0;
    String s;
    while ((testLine = br.readLine()) != null) {
            str += testLine + " ";
    }
    StringTokenizer st = new StringTokenizer(str);
    while (st.hasMoreTokens()) {
            s = st.nextToken();
            webWords.add(s);
            count++;
    }

现在我可以以类似的方式轻松创建两个 HashSet,但我目前正在使用 ArrayList,因为它允许重复,我仍然不确定哪个最适合我的需求。

我需要将第二个列表与第一个进行比较,并删除第二个列表中出现在第一个列表中的所有单词。

我的第二个问题是试图确定(在我删除常用词之后)哪些词最常出现。

任何帮助或指导将不胜感激。

【问题讨论】:

    标签: java arraylist hashset


    【解决方案1】:

    如果我正确理解要求,那么我们可以使用HashMap&lt;String, Integer&gt; 并将 list1 中的所有单词作为键,从而避免重复

    for(String w : list1) {
          map.put(w, 0);
    }
    

    然后我们可以遍历地图条目,计算词频并将其作为条目值

    for(Entry<String, Integer> e : map.entrySet) {
          int n = Collections.frequency(list2, e.getKey());
          e.setValue(n);
    }
    

    UPDATE:“我希望能够从 list2 中删除出现在 list1 中的单词。然后遍历 list2 中剩余的单词以找出每个单词出现的次数”

       list2.removeAll(list1);
    
       for(String w : list2) {
              map.put(w, 0);
        }
    
        for(Entry<String, Integer> e : map.entrySet) {
              int n = Collections.frequency(list2, e.getKey());
              e.setValue(n);
        }
    

    【讨论】:

    • 谢谢你,Evgeniy!但是,据我所见,此代码检查 list1 中的单词在列表 2 中出现的次数。这很好,但我想要做的是从 list2 中删除出现在 list1 中的单词。然后遍历list2中剩余的单词,找出每个单词出现了多少次。
    • 谢谢Evgeniy!非常感激。现在我可以按值排序来显示最常用的单词。再次感谢,我一直在尝试与以下类似的努力,但这更适合我的需求。
    【解决方案2】:

    要删除一个集合中存在于另一个集合中的所有元素,请使用removeAll。这是Collection接口中的可选操作,ArrayList和HashSet都实现了。

    words.removeAll(webWords);
    

    要构建频率表,您必须不要使用 Set,因为 Set 只保留每个元素中的一个。您需要使用一个列表并创建一个Map&lt;String, Integer&gt; 来将每个单词映射到它出现的次数。要构建它,您可以执行以下操作:

    for (String word : words) {
        if (freqMap.containsKey(word)) {
            freqMap.put(word, freqMap.get(word) + 1); // increment
        } else {
            freqMap.put(word, 1); // begin at 1 if it was not present
        }
    }
    

    【讨论】:

      【解决方案3】:

      组合术语和计数的简单方法是使用 HashMap,其中单词作为键,出现次数作为值。我不记得 Java 的确切表示法,但我希望是这样的:

      HashMap words = new HashMap();
      while ( st.hasMoreTokens())
      {
         s = st.nextToken();
         if ( words.containsKey(s) )
          {
              // probably not how indexing is done, but would be in most languages :p
              words[s]= words[s]+1;
           }
         else 
           {
             words.put( s, 1 );
           }
      }
      

      这样你最终会得到一个包含所有唯一单词的 HashMap 以及每个单词的出现次数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-27
        • 1970-01-01
        • 2016-08-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多