найти самое популярное слово в твитах человека - PullRequest
1 голос
/ 18 января 2020

В проекте я пытаюсь запросить твиты дескриптора конкретного пользователя и найти наиболее распространенное слово в твитах пользователя, а также вернуть частоту этого наиболее распространенного слова.

Ниже приведен мой code:

  public String mostPopularWord()
  {
     this.removeCommonEnglishWords();
     this.sortAndRemoveEmpties();

     Map<String, Integer> termsCount = new HashMap<>();
     for(String term : terms)
     {
        Integer c = termsCount.get(term);
        if(c==null)
           c = new Integer(0);
        c++;
        termsCount.put(term, c);
     }
     Map.Entry<String,Integer> mostRepeated = null;
     for(Map.Entry<String, Integer> curr: termsCount.entrySet())
     {
         if(mostRepeated == null || mostRepeated.getValue()<curr.getValue())
             mostRepeated = curr;
     }

     //frequencyMax = termsCount.get(mostRepeated.getKey());

     try 
     {
        frequencyMax = termsCount.get(mostRepeated.getKey());
        return mostRepeated.getKey();
     } 
     catch (NullPointerException e) 
     {
        System.out.println("Cannot find most popular word from the tweets.");
     }

     return ""; 
  }

Я также думаю, что было бы полезно показать коды для первых двух методов, которые я вызываю в методе выше, как показано ниже. Они все в одном классе, с определением следующего:

  private Twitter twitter;
  private PrintStream consolePrint;
  private List<Status> statuses;
  private List<String> terms;
  private String popularWord;
  private int frequencyMax;

  @SuppressWarnings("unchecked")
  public void sortAndRemoveEmpties()
  {
     Collections.sort(terms);
     terms.removeAll(Arrays.asList("", null));
  }

  private void removeCommonEnglishWords()
  {          
     Scanner sc = null;

     try
     {
        sc = new Scanner(new File("commonWords.txt"));
     }
     catch(Exception e)
     {
        System.out.println("The file is not found");
     }

     List<String> commonWords = new ArrayList<String>(); 
     int count = 0;
     while(sc.hasNextLine())
     {
        count++;
        commonWords.add(sc.nextLine()); 
     }

     Iterator<String> termIt = terms.iterator();
     while(termIt.hasNext())
     {
        String term = termIt.next();
        for(String word : commonWords)
           if(term.equalsIgnoreCase(word))
              termIt.remove();
     }
  }

Я прошу прощения за довольно длинные фрагменты кода. Но одна неприятная вещь заключается в том, что, хотя мой метод removeCommonEngli sh (), по-видимому, правильный (обсуждается в другом посте), когда я запускаю mostPopularWord (), он возвращает «the», который явно является частью общего Engli sh Список слов, которые я имею и хочу исключить из списка терминов. Что я могу делать не так?

ОБНОВЛЕНИЕ 1: Вот ссылка на файл commonWords: https://drive.google.com/file/d/1VKNI-b883uQhfKLVg-L8QHgPTLNb22uS/view?usp=sharing

ОБНОВЛЕНИЕ 2: Во время отладки я заметил одну вещь: c .hasNext ()) в removeCommonEnglishWords () полностью пропущен. Хотя я не понимаю почему.

Ответы [ 3 ]

2 голосов
/ 18 января 2020

Это может быть проще, если вы используете поток так:

String mostPopularWord() {
    return terms.stream()
            .collect(Collectors.groupingBy(s -> s, Collectors.counting()))
            .entrySet().stream()
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .findFirst()
            .map(Map.Entry::getKey)
            .orElse("");
}
0 голосов
/ 18 января 2020

Немного другой подход с использованием потоков.

  1. При этом используется относительно распространенная идиома подсчета частот с использованием потоков и сохраняется их на карте.
  2. Затем выполняется простое сканирование, чтобы найти получено наибольшее значение и оно возвращает либо слово, либо строку «Слова не найдены».
  3. Он также отфильтровывает слова в Set<String>, называемом ignore, так что вам нужно создать это тоже.

           import java.util.Arrays;
           import java.util.Comparator;
           import java.util.Map;
           import java.util.Map.Entry;
           import java.util.stream.Collectors;

            Set<String> ignore = Set.of("the", "of", "and", "a",
            "to", "in", "is", "that", "it", "he", "was",
            "you", "for", "on", "are", "as", "with",
            "his", "they", "at", "be", "this", "have",
            "via", "from", "or", "one", "had", "by",
            "but", "not", "what", "all", "were", "we",
            "RT", "I", "&", "when", "your", "can",
            "said", "there", "use", "an", "each",
            "which", "she", "do", "how", "their", "if",
            "will", "up", "about", "out", "many",
            "then", "them", "these", "so", "some",
            "her", "would", "make", "him", "into",
            "has", "two", "go", "see", "no", "way",
            "could", "my", "than", "been", "who", "its",
            "did", "get", "may", "…", "@", "??", "I'm",
            "me", "u", "just", "our", "like");


            Map.Entry<String, Long> entry = terms.stream()
                 .filter(wd->!ignore.contains(wd)).map(String::trim)
                .collect(Collectors.groupingBy(a -> a,
                        Collectors.counting()))
                .entrySet().stream()
                .collect(Collectors.maxBy(Comparator
                        .comparing(Entry::getValue)))
                .orElse(Map.entry("No words found", 0L));


              System.out.println(entry.getKey() + " " + entry.getValue());
0 голосов
/ 18 января 2020

Я попробовал твой код. Вот что вам нужно сделать. Замените следующую часть в removeCommonEnglishWords()

Iterator<String> termIt = terms.iterator();
while(termIt.hasNext())
{
   String term = termIt.next();
   for(String word : commonWords)
      if(!term.equalsIgnoreCase(word))
           reducedTerms.add( term );
}

следующим:

 List<String> reducedTerms = new ArrayList<>();
 for( String term : this.terms ) {
     if( !commonWords.contains( term ) ) reducedTerms.add( term );
 }

 this.terms = reducedTerms;

Так как вы не предоставили класс, я создал один с некоторыми предположениями, но я думаю, что этот код будет go до.

...