Программа Java Inverted Index

Я пишу инвертированную индексную программу на Java, которая возвращает частоту терминов среди нескольких документов. Мне удалось вернуть число раз, когда слово появляется во всей коллекции, но я не смог вернуть, в каких документах слово встречается. Вот код, который у меня есть:

import java.util.*;  // Provides TreeMap, Iterator, Scanner  
import java.io.*;    // Provides FileReader, FileNotFoundException  

public class Run
{
    public static void main(String[ ] args)
    {
        // **THIS CREATES A TREE MAP**  
        TreeMap<String, Integer> frequencyData = new TreeMap<String, Integer>( );

        Map[] mapArray = new Map[5];
        mapArray[0] = new HashMap<String, Integer>();

        readWordFile(frequencyData);
        printAllCounts(frequencyData);
    }


    public static int getCount(String word, TreeMap<String, Integer> frequencyData)
    {
        if (frequencyData.containsKey(word))
        {  // The word has occurred before, so get its count from the map  
            return frequencyData.get(word); // Auto-unboxed  
        }
        else
        {  // No occurrences of this word  
            return 0;
        }
    }


    public static void printAllCounts(TreeMap<String, Integer> frequencyData)
    {
        System.out.println("-----------------------------------------------");
        System.out.println("    Occurrences    Word");

        for(String word : frequencyData.keySet( ))
        {
            System.out.printf("%15d    %s\n", frequencyData.get(word), word);
        }

        System.out.println("-----------------------------------------------");
    }


    public static void readWordFile(TreeMap<String, Integer> frequencyData)
    {
        int total = 0;
        Scanner wordFile;
        String word;     // A word read from the file  
        Integer count;   // The number of occurrences of the word
        int counter = 0;
        int docs = 0;

        //**FOR LOOP TO READ THE DOCUMENTS**  
        for(int x=0; x<Docs.length; x++)
        { //start of for loop [*  

            try
            {
                wordFile = new Scanner(new FileReader(Docs[x]));
            }
            catch (FileNotFoundException e)
            {
                System.err.println(e);
                return;
            }

            while (wordFile.hasNext( ))
            {
                // Read the next word and get rid of the end-of-line marker if needed:  
                word = wordFile.next( );

                // This makes the Word lower case.  
                word = word.toLowerCase();

                word = word.replaceAll("[^a-zA-Z0-9\\s]", "");

                // Get the current count of this word, add one, and then store the new count:  
                count = getCount(word, frequencyData) + 1;
                frequencyData.put(word, count);
                total = total + count;
                counter++;
                docs = x + 1;

            }

        } //End of for loop *]  
        System.out.println("There are " + total + " terms in the collection.");
        System.out.println("There are " + counter + " unique terms in the collection.");
        System.out.println("There are " + docs + " documents in the collection.");

    }


    // Array of documents  
    static String Docs [] = {"words.txt", "words2.txt",};

3 ответа

Вместо того чтобы просто иметь Карту из слова в счет, создайте Карту из каждого слова во вложенную Карту из документа в счет. Другими словами:

Map<String, Map<String, Integer>> wordToDocumentMap;

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

Map<String, Integer> documentToCountMap = wordToDocumentMap.get(currentWord);
if(documentToCountMap == null) {
    // This word has not been found anywhere before,
    // so create a Map to hold document-map counts.
    documentToCountMap = new TreeMap<>();
    wordToDocumentMap.put(currentWord, documentToCountMap);
}
Integer currentCount = documentToCountMap.get(currentDocument);
if(currentCount == null) {
    // This word has not been found in this document before, so
    // set the initial count to zero.
    currentCount = 0;
}
documentToCountMap.put(currentDocument, currentCount + 1);

Теперь вы регистрируете счет по каждому слову и по каждому документу.

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

for(Map.Entry<String, Map<String,Integer>> wordToDocument :
        wordToDocumentMap.entrySet()) {
    String currentWord = wordToDocument.getKey();
    Map<String, Integer> documentToWordCount = wordToDocument.getValue();
    for(Map.Entry<String, Integer> documentToFrequency :
            documentToWordCount.entrySet()) {
        String document = documentToFrequency.getKey();
        Integer wordCount = documentToFrequency.getValue();
        System.out.println("Word " + currentWord + " found " + wordCount +
                " times in document " + document);
    }
}

Объяснение структуры for-each в Java см. На этой странице учебника.

Для хорошего объяснения функций интерфейса карты, в том числе entrySet метод, см. эту страницу учебника.

Я поместил сканер в основной метод, и слово, которое я ищу, вернет документы, в которых встречается слово. Я также возвращаю, сколько раз слово встречается, но я получу только общее количество раз за все из трех документов. И я хочу, чтобы он возвращал, сколько раз это происходит в каждом документе. Я хочу, чтобы это было в состоянии рассчитать TF-IDF, если у вас есть полный ответ для всего TF-IDF, я был бы признателен. ура

Вот мой код:

import java.util.*;  // Provides TreeMap, Iterator, Scanner  
import java.io.*;    // Provides FileReader, FileNotFoundException  

public class test2
{

    public static void main(String[ ] args)
    {
        // **THIS CREATES A TREE MAP**  
        TreeMap<String, Integer> frequencyData = new TreeMap<String, Integer>();
        Map<String, Set<String>> filenames = new HashMap<String, Set<String>>();
        Map<String, Integer> countByWords = new HashMap<String, Integer>();

        Map[] mapArray = new Map[5];
        mapArray[0] = new HashMap<String, Integer>();

        readWordFile(countByWords, frequencyData, filenames);
        printAllCounts(countByWords, frequencyData, filenames);
    }


    public static int getCount(String word, TreeMap<String, Integer> frequencyData)
    {

        if (frequencyData.containsKey(word))
        {  // The word has occurred before, so get its count from the map  
            return frequencyData.get(word); // Auto-unboxed  
        }
        else
        {  // No occurrences of this word  
            return 0;
        }
    }



    public static void printAllCounts(  Map<String, Integer> countByWords, TreeMap<String, Integer> frequencyData, Map<String, Set<String>> filenames)
    {
        System.out.println("-----------------------------------------------");
        System.out.print("Search for a word: ");

        String worde;
        int result = 0;
        Scanner input = new Scanner(System.in);
        worde=input.nextLine();

        if(!filenames.containsKey(worde)){
            System.out.println("The word does not exist");
        }

        else{
            for(String filename : filenames.get(worde)){


                System.out.println(filename);
                System.out.println(countByWords.get(worde));




            }


        }

        System.out.println("\n-----------------------------------------------");
    }


    public static void readWordFile(Map<String, Integer> countByWords ,TreeMap<String, Integer> frequencyData, Map<String, Set<String>> filenames)
    {
        Scanner wordFile;
        String word;     // A word read from the file  
        Integer count; // The number of occurrences of the word
        int counter = 0;

        int docs = 0;

        //**FOR LOOP TO READ THE DOCUMENTS**  
        for(int x=0; x<Docs.length; x++)
        { //start of for loop [*  

            try
            {
                wordFile = new Scanner(new FileReader(Docs[x]));
            }
            catch (FileNotFoundException e)
            {
                System.err.println(e);
                return;
            }

            while (wordFile.hasNext( ))
            {
                // Read the next word and get rid of the end-of-line marker if needed:  
                word = wordFile.next( );

                // This makes the Word lower case.  
                word = word.toLowerCase();

                word = word.replaceAll("[^a-zA-Z0-9\\s]", "");

                // Get the current count of this word, add one, and then store the new count:  
                count = countByWords.get(word);
                if(count != null){
                    countByWords.put(word, count + 1);
                }



                else{
                    countByWords.put(word, 1);
                }
                Set<String> filenamesForWord = filenames.get(word);
                if (filenamesForWord == null) {
                    filenamesForWord = new HashSet<String>();

                }

                filenamesForWord.add(Docs[x]);
                filenames.put(word, filenamesForWord);
                counter++;
                docs = x + 1;

            }




        } //End of for loop *]  
        System.out.println("There are " + counter + " terms in the collection.");
        System.out.println("There are " + docs + " documents in the collection.");

    }


    // Array of documents  
    static String Docs [] = {"Document1.txt", "Document2.txt", "Document3.txt"};

}  

Попробуйте добавить вторую карту word -> set of document name как это:

Map<String, Set<String>> filenames = new HashMap<String, Set<String>>();

...
word = word.replaceAll("[^a-zA-Z0-9\\s]", ""); 

// Get the current count of this word, add one, and then store the new count:  
count = getCount(word, frequencyData) + 1;  
frequencyData.put(word, count);
Set<String> filenamesForWord = filenames.get(word);
if (filenamesForWord == null) {
    filenamesForWord = new HashSet<String>();
}
filenamesForWord.add(Docs[x]);
filenames.put(word, filenamesForWord);
total = total + count;
counter++;
docs = x + 1;

Когда вам нужно получить набор имен файлов, в которых вы встретили определенное слово, вы просто get() это с карты filenames, Вот пример, который распечатывает все имена файлов, в которых мы встретили слово:

public static void printAllCounts(TreeMap<String, Integer> frequencyData, Map<String, Set<String>> filenames) {
    System.out.println("-----------------------------------------------");
    System.out.println("    Occurrences    Word");

    for(String word : frequencyData.keySet( ))
    {
        System.out.printf("%15d    %s\n", frequencyData.get(word), word);
        for (String filename : filenames.get(word)) {
            System.out.println(filename);
        } 
    }

    System.out.println("-----------------------------------------------");
}
Другие вопросы по тегам