Сравнение двух списков строк для похожих слов и измерения частоты встречающихся слов - JAVA

Я понимаю, что задаю сразу два отдельных вопроса, но думаю, что они связаны (хотя бы немного). В любом случае, я хочу сравнить два списка (не обязательно списки Java) строк и удалить слова, которые встречаются в обоих списках. Я думал использовать либо ArrayList , либо HashSet с HashSet , который предпочитается, поскольку списки не упорядочены, но моя проблема с HashSet заключается в том, что Я читал, что они не позволяют дублировать. Это немного противоречит моему другому требованию, поскольку я хочу, чтобы уметь подсчитывать количество раз каждое слово, но показывать их только один раз ... если это имеет смысл. Подумайте о примере WordCloud.

Вот что я имею в настоящее время, сохраняя содержимое двух текстовых файлов на два ArrayList s:

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

Мне пришлось использовать два разных способа сохранения данных, поскольку два текстовых файла были структурированы по-разному

ArrayList webWords = new ArrayList();
    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++;
    }

Теперь я мог бы легко создать два HashSets аналогичным образом, но на данный момент я использую ArrayList, поскольку он позволяет дублировать, и я по-прежнему не уверен, что подходит для моих потребностей лучше всего.

Мне нужно сравнить второй список с первым и удалить все слова во втором списке, которые появляются в первом списке.

Моя вторая проблема пытается определить (после того, как я удалил общие слова), какие слова встречаются наиболее часто.

Любая помощь или направление были бы весьма признательны.

1

5 ответы

If I understand the requierements correctly then we can take a HashMap and put all words from list1 in it as keys, thus we avoid duplicates

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

то мы можем перебирать записи карты, подсчитывать частоту слов и ставить ее как значение записи

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

UPDATE: "I want to be able to remove the words from list2 that appear in list1. And then iterate through the remaining words in list2 to find out how many times each word occurs"

   list2.removeAll(list1);

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

    for(Entry e : map.entrySet) {
          int n = Collections.frequency(list2, e.getKey());
          e.setValue(n);
    }
3
добавлено
Спасибо, Евгений! Однако из того, что я вижу, этот код проверяет, сколько раз слова в списке1 встречаются в списке 2. Это прекрасно, но то, что я хочу сделать, это удалить слова из списка2, которые появляются в списке1. И затем перебирайте оставшиеся слова в списке2, чтобы узнать, сколько раз каждое слово происходит.
добавлено автор UserBruiser, источник
Спасибо, Евгений! Очень признателен. Теперь я могу, может быть, заказать по стоимости, чтобы отображать наиболее часто используемые слова. Еще раз спасибо, я пробовал аналогичные усилия, как и ниже, но это лучше всего подходит моим потребностям.
добавлено автор UserBruiser, источник
Посмотрите мое обновление, надеюсь, на этот раз я понял
добавлено автор Evgeniy Dorofeev, источник

If I understand the requierements correctly then we can take a HashMap and put all words from list1 in it as keys, thus we avoid duplicates

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

то мы можем перебирать записи карты, подсчитывать частоту слов и ставить ее как значение записи

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

UPDATE: "I want to be able to remove the words from list2 that appear in list1. And then iterate through the remaining words in list2 to find out how many times each word occurs"

   list2.removeAll(list1);

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

    for(Entry e : map.entrySet) {
          int n = Collections.frequency(list2, e.getKey());
          e.setValue(n);
    }
3
добавлено
Спасибо, Евгений! Однако из того, что я вижу, этот код проверяет, сколько раз слова в списке1 встречаются в списке 2. Это прекрасно, но то, что я хочу сделать, это удалить слова из списка2, которые появляются в списке1. И затем перебирайте оставшиеся слова в списке2, чтобы узнать, сколько раз каждое слово происходит.
добавлено автор UserBruiser, источник
Спасибо, Евгений! Очень признателен. Теперь я могу, может быть, заказать по стоимости, чтобы отображать наиболее часто используемые слова. Еще раз спасибо, я пробовал аналогичные усилия, как и ниже, но это лучше всего подходит моим потребностям.
добавлено автор UserBruiser, источник
Посмотрите мое обновление, надеюсь, на этот раз я понял
добавлено автор Evgeniy Dorofeev, источник

Чтобы удалить все элементы одной коллекции, которые присутствуют в другой, используйте removeAll . Это необязательная операция в интерфейсе Collection, и как ArrayList, так и HashSet реализуют ее.

words.removeAll(webWords);

To build a frequency table, you must not be using a Set, since Sets only keep one of each element. You'll want to use a List and create a Map to map each word to the number of times it appears. To build it, you can do something like this:

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
    }
}
1
добавлено

Чтобы удалить все элементы одной коллекции, которые присутствуют в другой, используйте removeAll . Это необязательная операция в интерфейсе Collection, и как ArrayList, так и HashSet реализуют ее.

words.removeAll(webWords);

To build a frequency table, you must not be using a Set, since Sets only keep one of each element. You'll want to use a List and create a Map to map each word to the number of times it appears. To build it, you can do something like this:

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
    }
}
1
добавлено

Простым способом выполнения комбинации терминов и подсчетов является использование 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 всех уникальных слов и количество выступлений для каждого из них.

0
добавлено
pro.jvm
pro.jvm
3 503 участник(ов)

Сообщество разработчиков Java Scala Kotlin Groovy Clojure Чат для нач-их: @javastart Наш сайт: projvm.com projvm.ru Наш канал: @proJVM Вакансии: @jvmjobs Конфы: @jvmconf

Java & Co
Java & Co
2 370 участник(ов)

Можно обсуждать с матом и без всё, что касается жабы, вплоть до холиваров. НЕ ИМЕЕТ ОТНОШЕНИЯ К САЙТУ JAVARUSH.RU ПРАВИЛА - https://t.me/javarush/75723 Вакансии сюда - https://telegram.me/joinchat/B7IzvUCnfo6d8t3yIxKguQ По вопросам - @thedude

learn.java
learn.java
1 888 участник(ов)

Чат для начинающих и не только Статистика: https://combot.org/chat/-1001083535868 Основной чат - @jvmchat

Java Underground
Java Underground
169 участник(ов)

https://vk.com/javatutorial

Javanese Questions
Javanese Questions
109 участник(ов)

Чат предназначен для обмена знаниями строго в формате в вопрос-ответ. Тема — Java, Kotlin и Android. Вопрос должен быть предварительно прогуглен, понятно и грамотно сформулирован, помечен хэштегами. Ответ — тем более. Куски кода размером в несколько строк можно писать прямо здесь, для больших кусков кода стоит использовать http://gist.github.com/, http://pastebin.com/, https://codeshare.io/ или любой аналогичный сервис. В некоторых случаях можно прикреплять скриншоты. Стикеры и гифки запрещены. Дополнять и уточнять вопросы и ответы — редактированием исходного сообщения. Обсуждения должны приводить к редактированию вопроса/ответа и удаляться. По хештегам можно искать существующие вопросы и овтеты: #вопрос #ответ #git #generics #java #server #awt #javafx #swing #kotlin #anko #tornadofx #ktor #android #recyclerView #performance #arch #network #permissions #storage #async